<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>Juan de Bravo</title>
 <link href="http://feeds.feedburner.com/juandebravo" rel="self"/>
 <link href="http://juandebravo.com"/>
 <updated>2025-04-13T19:51:09+00:00</updated>
 <id>http://juandebravo.com</id>
 <author>
   <name>Juan de Bravo</name>
   <email>juandebravo@gmail.com</email>
 </author>

 
 <entry>
   <title>Configure MCP server with asdf for Node.js</title>
   <link href="http://juandebravo.com/2025/04/12/configure-mcp-server-with-asdf/"/>
   <updated>2025-04-12T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2025/04/12/configure-mcp-server-with-asdf/</id>
   <content type="html">&lt;p&gt;Today I want to share how to configure an &lt;a href=&quot;https://modelcontextprotocol.io/&quot;&gt;MCP (Model Context Protocol)&lt;/a&gt; server to run Node.js applications using &lt;a href=&quot;https://asdf-vm.com/&quot;&gt;asdf&lt;/a&gt; as the version manager. This setup is particularly useful when you need to ensure consistent Node.js versions across different environments and want to leverage asdf’s powerful version management capabilities.&lt;/p&gt;

&lt;h2 id=&quot;the-challenge&quot;&gt;The Challenge&lt;/h2&gt;

&lt;p&gt;When setting up an MCP server to run Node.js applications, you might encounter issues with Node.js version management and environment variables. The key is to ensure that the MCP server can find and use the correct Node.js version managed by asdf.&lt;/p&gt;

&lt;h2 id=&quot;the-solution&quot;&gt;The Solution&lt;/h2&gt;

&lt;p&gt;Here’s a working configuration example for an MCP server that runs a Node.js application:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;mcpServers&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;your-mcp-server&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;command&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;node&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;args&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/Users/foo/projects/mcp-server/build/index.js&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;env&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;PATH&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/Users/foo/.asdf/shims:/usr/local/bin:/usr/bin:/bin&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ASDF_DIR&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/Users/foo/.asdf&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ASDF_DATA_DIR&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/Users/foo/.asdf&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ASDF_NODEJS_VERSION&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;22.14.0&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s break down the important parts of this configuration:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Environment Variables&lt;/strong&gt;:
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PATH&lt;/code&gt;: Includes the asdf shims directory first, ensuring that asdf-managed executables are found before system ones.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ASDF_DIR&lt;/code&gt;: Points to your asdf installation directory.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ASDF_DATA_DIR&lt;/code&gt;: Specifies where asdf stores its data.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ASDF_NODEJS_VERSION&lt;/code&gt;: Explicitly sets the Node.js version to use.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Command Configuration&lt;/strong&gt;:
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;command&lt;/code&gt;: Set to “node” to use the Node.js executable.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;args&lt;/code&gt;: Contains the path to your Node.js application’s entry point.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;why-this-works&quot;&gt;Why This Works&lt;/h2&gt;

&lt;p&gt;The configuration works because it:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Ensures the correct Node.js version is used by setting the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ASDF_NODEJS_VERSION&lt;/code&gt; environment variable&lt;/li&gt;
  &lt;li&gt;Makes asdf-managed executables available by adding the shims directory to the PATH&lt;/li&gt;
  &lt;li&gt;Provides all necessary asdf environment variables for proper version management&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;tips-for-implementation&quot;&gt;Tips for Implementation&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Make sure you have the Node.js version installed in asdf:
    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;asdf &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;nodejs 22.14.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Verify the version is available:
    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;asdf list nodejs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Adjust the paths in the configuration to match your system’s setup:
    &lt;ul&gt;
      &lt;li&gt;Replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Users/foo&lt;/code&gt; with your home directory&lt;/li&gt;
      &lt;li&gt;Update the application path to point to your Node.js application&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;If you’re using a different Node.js version, update the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ASDF_NODEJS_VERSION&lt;/code&gt; accordingly&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;troubleshooting&quot;&gt;Troubleshooting&lt;/h2&gt;

&lt;p&gt;If you encounter issues:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Verify that the Node.js version specified in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ASDF_NODEJS_VERSION&lt;/code&gt; is installed.&lt;/li&gt;
  &lt;li&gt;Check that all paths in the configuration are correct.&lt;/li&gt;
  &lt;li&gt;Ensure the asdf shims directory is properly set up.&lt;/li&gt;
  &lt;li&gt;Try running the Node.js application directly from the command line to verify it works.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This configuration provides a robust way to run Node.js applications through MCP while maintaining version consistency through asdf. It’s particularly useful in development environments where you need to switch between different Node.js versions for different projects.&lt;/p&gt;

&lt;p&gt;For more information about MCP, check out the &lt;a href=&quot;https://modelcontextprotocol.io/&quot;&gt;official documentation&lt;/a&gt;. For asdf, visit the &lt;a href=&quot;https://asdf-vm.com/&quot;&gt;asdf website&lt;/a&gt; or their &lt;a href=&quot;https://github.com/asdf-vm/asdf&quot;&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy coding! 🚀&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Get Pull Request metrics with chat-gpt</title>
   <link href="http://juandebravo.com/2023/03/27/get-pull-requests-metrics-with-chat-gpt/"/>
   <updated>2023-03-27T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2023/03/27/get-pull-requests-metrics-with-chat-gpt/</id>
   <content type="html">&lt;p&gt;I woke up early morning today and took some minutes to read &lt;a href=&quot;https://leaddev.com/scaling-software-systems/primer-engineering-delivery-metrics&quot;&gt;this blog post about
engineering delivery metrics&lt;/a&gt; while grabbing my early morning coffee :coffee:.&lt;/p&gt;

&lt;p&gt;It provides good insights about how to measure the efficiency of your
process from a Pull Request being opened until the code changes are shipped to the
production environment.&lt;/p&gt;

&lt;p&gt;Without going into low-level details, these are the main things that should
happen during that process:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/github-metrics/delivery_process.png&quot; alt=&quot;Delivery pipeline&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The concepts described in that blog post are something that has been running as a background thread in my mind over
the last few months, but I am always struggling to invest some time in it.&lt;/p&gt;

&lt;p&gt;Until today! I paired with ChatGPT and I hit two targets with one shot.&lt;/p&gt;

&lt;p&gt;I was curious about the first part of the diagram above: how long does it take for a Pull Request to get merged in my current project?&lt;/p&gt;

&lt;p&gt;I asked:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/github-metrics/first-question.png&quot; alt=&quot;First question&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And GPT replied:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/github-metrics/first-answer.png&quot; alt=&quot;First answer&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This was a good way to start our relationship for this matter :blush: It helped me to avoid:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;checking which python library should I use.&lt;/li&gt;
  &lt;li&gt;check the github / python library API to understand how to obtain each pull request and its status.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I realized my question was misleading, as it interpreted that I was interested in a specific Pull Request:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/github-metrics/second-question.png&quot; alt=&quot;Second question&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And GPT replied:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/github-metrics/second-answer.png&quot; alt=&quot;Second answer&quot; /&gt;
&lt;img src=&quot;/gfx/posts/github-metrics/second-answer-2.png&quot; alt=&quot;Second answer&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I was so impressed that I didn’t even consider testing the script, I wanted more!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/github-metrics/third-question.png&quot; alt=&quot;Third question&quot; /&gt;&lt;/p&gt;

&lt;p&gt;For the sake of readiness, I’ve put its answer in &lt;a href=&quot;https://gist.github.com/juandebravo/abef866d259d610d987a9f3e08551210&quot;&gt;an external gist&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And its explanation:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/github-metrics/third-answer-2.png&quot; alt=&quot;Third answer&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It hadn’t in mind that I was curious about the last six months of activity, and it decided to query Pull Requests from a specific date (yesterday).&lt;/p&gt;

&lt;p&gt;So I asked again:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/github-metrics/fourth-question.png&quot; alt=&quot;Fourth question&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And its answer in &lt;a href=&quot;https://gist.github.com/juandebravo/9c23aec131deef9f04877ba403f64d46&quot;&gt;an external gist&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It described again the solution, but to be honest I didn’t read it.&lt;/p&gt;

&lt;p&gt;At this point, I’m not sure if there’s been a big gain in productivity. Perhaps the major advantage is that I didn’t need to
invest some time reviewing a couple of third-party dependencies, but at the same time, I feel I’m trusting blindly what I’m being told.&lt;/p&gt;

&lt;p&gt;Unfortunately, things became a bit tedious:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/github-metrics/fifth-question.png&quot; alt=&quot;Fifth question&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It apologized for the confusion (so cute :cat:) and pointed to the mistake very fast (incredibly fast!)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/github-metrics/fifth-answer.png&quot; alt=&quot;Fifth answer&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This got me very confused and intrigued. I could understand that ChatGPT knew about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;since&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;until&lt;/code&gt; attributes in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get_pulls()&lt;/code&gt; method if they had existed in previous versions of the &lt;em&gt;PyGithub&lt;/em&gt; library and got deprecated for whatever reason in the last version of the library. But that was not the case, they have never existed. So I have no idea why ChatGPT decided to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;since&lt;/code&gt;. My two theories are that it exists in other libraries and learned from that, or it extrapolated other arguments of the REST
API and adapted its knowledge about the python wrapper. Quite fascinating IMO even though it was wrong this time.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://gist.github.com/juandebravo/9ca2ea70d9d38c029809763871f9b1b8&quot;&gt;This is the script&lt;/a&gt; associated with the response above. Here GPT made
a rookie mistake. We are interested in the last 6 months of data, so as soon as one Pull Request is older than that, we can stop iterating over
previous data (pull requests are order by time desc).&lt;/p&gt;

&lt;p&gt;I got a couple of additional errors:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/github-metrics/sixth-question.png&quot; alt=&quot;Sixth question&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://gist.github.com/juandebravo/ebcd982e74a2d5da88700faa63f6f309&quot;&gt;This script&lt;/a&gt; is interesting because it forgot to add the last line of the script:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This reminded me to don’t trust blindly the machine for now. So I read the script for the first time :laughing: and realized we were
retrieving data from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; branch. I can understand that because it used to be the default branch name some years ago, but &lt;a href=&quot;https://www.theserverside.com/feature/Why-GitHub-renamed-its-master-branch-to-main&quot;&gt;that’s not the
case anymore&lt;/a&gt; :punch:.&lt;/p&gt;

&lt;p&gt;I suggested using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; as the default branch instead:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/github-metrics/seventh-question.png&quot; alt=&quot;Seventh question&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It was very polite, I was liking it a lot:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/github-metrics/seventh-answer.png&quot; alt=&quot;Seventh answer&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Going back to my previous problem, it was still happening!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/github-metrics/eigth-question.png&quot; alt=&quot;Eighth question&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And its answer and &lt;a href=&quot;https://gist.github.com/juandebravo/b49db9d84e9803e780bf1741dd2e8c04&quot;&gt;the updated script&lt;/a&gt;, this time with the last line included!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/github-metrics/eigth-answer.png&quot; alt=&quot;Eighth answer&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Here we got an issue that should be easy to spot with the usual linter in your IDE:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/github-metrics/ninth-question.png&quot; alt=&quot;Ninth question&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And it acknowledged the mistake and provided &lt;a href=&quot;https://gist.github.com/juandebravo/0b9d0c57976ec70f7de6950b4b549698&quot;&gt;an updated script&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I was getting a very ugly chart with no data, so I thought maybe we should plot “hours to merge” instead of “days to merge”:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/github-metrics/tenth-question.png&quot; alt=&quot;Tenth question&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It explained briefly the required changes:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/github-metrics/tenth-answer.png&quot; alt=&quot;Tenth answer&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This is &lt;a href=&quot;https://gist.github.com/juandebravo/33ba2ff6bf9c827f12d243f6e4cdce1a&quot;&gt;the generated script&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this point, I think both of us needed a break :laughing:.&lt;/p&gt;

&lt;p&gt;The chart was still looking pretty bad, so I did what I usually (try to) do in my day-to-day work: read the code,
understand what it’s doing, add some helpful debug logs, and find the root cause of what’s going on.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/github-metrics/eleventh-question.png&quot; alt=&quot;Eleventh question&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This was still very interesting but was not increasing my productivity anymore. This is its answer:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/github-metrics/eleventh-answer.png&quot; alt=&quot;Eleventh answer&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I was shocked :laughing: It indeed understood the issue (we were using datetime instead of date to create the buckets) but suddenly
it introduced numpy (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;np.&lt;/code&gt;) in our script.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/github-metrics/twelfth-question.png&quot; alt=&quot;Twelfth question&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This is its answer and &lt;a href=&quot;https://gist.github.com/juandebravo/d15af79876e23e2c23c45af978004260&quot;&gt;the script using numpy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/github-metrics/twelfth-answer.png&quot; alt=&quot;Twelfth question&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I tested it and it worked :tada:. In less than one hour we had a script to grab the Pull Requests from a specific repo and plot a histogram
with the number of hours it took to merge each Pull Request.&lt;/p&gt;

&lt;p&gt;I think the job is still not ended, but it was a good start and I needed a break, so I asked it something different to have some social time together:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/github-metrics/last-question.png&quot; alt=&quot;Last question&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I left home at 11:00 am and the cyclist arrived at 12:30 pm. I was lucky I didn’t trust it blindly.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/github-metrics/bicycle.png&quot; alt=&quot;Bicycle&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>How to mount an external volume with write permissions</title>
   <link href="http://juandebravo.com/2023/03/26/mount-external-volume-write-permissions/"/>
   <updated>2023-03-26T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2023/03/26/mount-external-volume-write-permissions/</id>
   <content type="html">&lt;p&gt;I am always struggling to figure out how to fix “read-only permissions” when plugging an external USB into your Mac. If you are on my team, this has worked for me:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Get the list of mounted volumes:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;diskutil list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You will get a list of volumes, both internal (your hard disk(s)) and external (your USB).&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Identify the external one with read-only permissions (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/disk4&lt;/code&gt;) and unmount it:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;diskutil unmountDisk /dev/disk4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In my case it’s always &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/disk4&lt;/code&gt; :man_shrugging:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Create a folder where the USB will be mounted:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; /Volumes/EXTERNAL_USB
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Mount the USB again with write permissions:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;mount &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; exfat /dev/disk4s1 /Volumes/EXTERNAL_USB
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;where:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-w&lt;/code&gt; stands for write permissions.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-t exfat&lt;/code&gt; is the external type. It should match the format you used when formatting your USB (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exfat&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nfs&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msdos&lt;/code&gt;, etc).&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/disk4s1&lt;/code&gt; is the disk identifier + partition to mount.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Volumes/EXTERNAL_USB&lt;/code&gt; is the folder you created in step 3.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tricky thing to remember is the external type you should use. Valid options can be found by running:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; /sbin/mount_&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;cut&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c13-&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And that’s all. Hope it saves time for you, and it will save time for me from now on :laughing:.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>TID-X registration flow with Arengu</title>
   <link href="http://juandebravo.com/2020/03/15/tid-x-registration-flow-with-arengu/"/>
   <updated>2020-03-15T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2020/03/15/tid-x-registration-flow-with-arengu/</id>
   <content type="html">&lt;p&gt;Last week I was working on the &lt;a href=&quot;https://www.tid-x.com&quot;&gt;TID-X&lt;/a&gt; registration form; TID-X is a tech event
I co-organize with my friends &lt;a href=&quot;https://twitter.com/anarchyco&quot;&gt;Gustavo&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/alalga&quot;&gt;Alonso&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Given that &lt;a href=&quot;https://www.tid-x.com&quot;&gt;TID-X&lt;/a&gt; is a free event, registration is a very simple process: we
need to know approximate number of attendees, so we make sure we that venu capacity is not overflowed.&lt;/p&gt;

&lt;h3 id=&quot;registration-flow&quot;&gt;Registration flow&lt;/h3&gt;

&lt;p&gt;Despite its simplicity, the registration needs to include the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;A list of all attendees including their ID details&lt;/strong&gt;. All that is required by the security team at the hosting venue. So, we need to make sure that we collect
all data without disclosing private information.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;A list of attendees for the conference website&lt;/strong&gt;. TID-X is, mainly, a social
event focused on socializing with friends and colleagues but also meeting new
people, so getting to know who will be attending in advance is not only a cool
thing but also a useful one, if you want to make the most of your time there.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2020 will be the third TID-X edition, and in the previous ones, we (the
organizers) were tackled these requirements using two separate flows:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;private list for security&lt;/em&gt;: attendee should fill in her data in a Google Form.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;public list of attendees&lt;/em&gt;: attendee should send a Pull Request to TID-X repository including her name and personal URL.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Having two decoupled steps is the last thing you want for something like a registration flow :blush:. Also, the Pull Request step created some friction
for some attendees.&lt;/p&gt;

&lt;h3 id=&quot;welcome-arengu&quot;&gt;Welcome Arengu!&lt;/h3&gt;

&lt;p&gt;I was looking for options to merge these two flows into a single step, to
simplify the usability and streamline the signing up for our users. &lt;a href=&quot;https://github.com/tid-x/tid-x/&quot;&gt;TID-X web page&lt;/a&gt; is hosted in Github using &lt;a href=&quot;https://pages.github.com/&quot;&gt;Github Pages&lt;/a&gt;, and keeping the public list of attendees as part of the source code was definitely something I wanted to maintain (we’re serverless!).&lt;/p&gt;

&lt;p&gt;And then, I found &lt;strong&gt;Arengu&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.arengu.com/&quot;&gt;Arengu&lt;/a&gt; is a very interesting product that raised €500.000](https://tech.eu/brief/arengu-pre-seed/)
some weeks ago. Its goal is to help companies build their sign-up flows with ease. I’d define it as the &lt;strong&gt;intersection of
&lt;a href=&quot;https://auth0.com/&quot;&gt;Auth0&lt;/a&gt; and &lt;a href=&quot;https://www.typeform.com/&quot;&gt;Typeform&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Arengu has two main entities:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;form&lt;/em&gt;: usual functionalities you may expect if you’ve used Google Forms or TypeForm.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;flows&lt;/em&gt;: build business logic on top of a form.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Going back to the our TID-X needs, &lt;em&gt;list of attendees for the security team&lt;/em&gt; was very easy to implement. With Arengu you can view and export the form submissions.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/arengu-form.png&quot; alt=&quot;Arengu form view submissions&quot; /&gt;&lt;/p&gt;

&lt;p&gt;As for the &lt;em&gt;public list of attendees&lt;/em&gt;, it meant updating TID-X source code by adding the new attendee to the attendees list.&lt;/p&gt;

&lt;p&gt;That’s a very good fit for an Arengu flow: once the user has filled in the form, if she has accepted to be included in the attendees public list, a new pull request to the source code repository with the relevant user data would be generated:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/arengu-flow.png&quot; alt=&quot;Arengu flow to open a Pull Request&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Setting up a flow (business logic) was very straight forward. The HTTP Request step triggers a
&lt;a href=&quot;https://github.com/tid-x/tid-x/blob/master/.github/workflows/a%C3%B1adir-asistente.yml&quot;&gt;Github Action&lt;/a&gt;, which will eventually
create a Pull Request for adding the attendee name to the &lt;a href=&quot;https://www.tid-x.com/inscripcion&quot;&gt;attendees list&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://www.arengu.com/&quot;&gt;Arengu&lt;/a&gt; allowed us to merge the two registration flows we had without writing any code and without deploying any logic. Very cool! 🙌🏻🚀&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>I work remotely</title>
   <link href="http://juandebravo.com/2020/02/22/I-work-remotely/"/>
   <updated>2020-02-22T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2020/02/22/I-work-remotely/</id>
   <content type="html">&lt;p&gt;I have been working in the tech domain over the last twenty years (OMG!). During that period of time, I’ve transitioned
from the regular office environment to be fully remote. This is my personal experience so far, lessons learnt and
things I’m still struggling with.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’m working at &lt;a href=&quot;https://jamm.app&quot;&gt;Jamm&lt;/a&gt;, a video-first collaboration experience for modern teams. Our goal is to enable not only fast,
friction-free communication but also enable to collaborate meaningfully with a bunch of people regardless of location or timezone. You
can request access to our private beta &lt;a href=&quot;https://jammhq.typeform.com/to/m0mbZw&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/Jamm-logo.png&quot; alt=&quot;Jamm&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;
This is not a detailed explanation on the benefits of remote working but my personal experience. If you’re
interested in going deeper on the subject, I recommend the book &lt;a href=&quot;https://basecamp.com/books/remote&quot;&gt;REMOTE, office not required&lt;/a&gt;, by
&lt;a href=&quot;https://twitter.com/jasonfried&quot;&gt;@jasonfried&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/dhh&quot;&gt;@dhh&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;avoid-commuting-to-work&quot;&gt;Avoid commuting to work&lt;/h2&gt;

&lt;p&gt;Living in Barcelona, if you work for a company ordinarily offices are in the city center so getting to work will not
take you (or me!) more than 40 minutes; and that used to be my case (40 minutes max one way) before working from home.
Over the years I used the usual means of transport:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;metro&lt;/strong&gt;: a bit crowded in the mornings, fine in the afternoons. Very uncomfortable in summer time, when the humidity
  in Barcelona is at high peak. Good option to carve out some time to read.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;public bicycle system&lt;/strong&gt;: it works fine, even though it’s fairly common that you need to visit a couple of stations
  for picking up a bicycle or finding a free slot to leave it back. Things are getting better over time though.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;my own bicycle&lt;/strong&gt;: my favorite option. I had a 25 minutes ride to the office, good enough for doing
  some physical exercise without sweating. The city is well equipped with a network of bicycle lanes map here.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;scooter&lt;/strong&gt;: fastest option, but that’s the only advantage compared with the others, and it’s for sure the most dangerous one.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the best case (scooter), it would take me around 50 minutes (two ways) every day. Now that I’m working from home, I earned
that time, for free. 5 days a week during 11 months per year means roughly 183 hours per year, equivalent to around 22 days work
(a month!), 5000 km with my road bicycle or around 2000 km running. &lt;strong&gt;Every single year&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I’ve never been a fan of commuting so I’m taking this as a great improvement in my daily routine.&lt;/p&gt;

&lt;h2 id=&quot;get-your-working-space-right&quot;&gt;Get your working space right&lt;/h2&gt;

&lt;p&gt;Over the last years I’ve tried different options at home to find the right environment to work. We moved into our current apartment a couple of years ago; however it has just been this winter when I have the feeling that I found not only the room but also furniture, lighting and hardware that works for me. I tried several options before, but they were either too noisy, bright, dark or distracting.&lt;/p&gt;

&lt;p&gt;Previously, since working from home was very rare, having a dedicated space was not so key but now, with no office to go to,  it is important to find not only a suitable space to be productive, focused and, also important, being able to shut the door and separate my personal from my professional life.&lt;/p&gt;

&lt;h2 id=&quot;hardware&quot;&gt;Hardware&lt;/h2&gt;

&lt;p&gt;Last year I left my MacBook Pro 2017 as secondary device and acquired a PC. Not that I was planning to switch from macOS to Windows/Linux, but my
perceived performance of that laptop was extremelly low and I needed a change. I started thinking about setting up a Hackintosh,
and after getting some suggestions from &lt;a href=&quot;https://twitter.com/arturogdg&quot;&gt;Arturo&lt;/a&gt; about hardware and some help from &lt;a href=&quot;https://twitter.com/drslump&quot;&gt;Iván&lt;/a&gt; to set it up, I got it working. Find below the hardware that I used; overall I’m very happy with the outcome. Performance is much better and I’ve never got
infuriated due to my computer under performing (now I can only blame myself if I’m getting stuck!):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;CPU:&lt;/strong&gt;: Intel Core i7-8700K 3.7Ghz BOX.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Motherboard:&lt;/strong&gt;: Gigabyte Z390 Aorus Pro.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Memory&lt;/strong&gt;: Corsair Vengeance LPX DDR4 3200 PC4-25600 32GB.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SSD&lt;/strong&gt;: Samsung 860 EVO Basic SSD 500GB SATA3.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;CPU Cooler&lt;/strong&gt;:&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Power supply&lt;/strong&gt;: Corsair RM750X V2 750W 80 Plus Gold Modular.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tower case&lt;/strong&gt;: NZXT H500i.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Screen&lt;/strong&gt;: LG 34UC99-W.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Webcam&lt;/strong&gt;: Logitech C930e.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There’re a lot of specs about Hackintosh hardware setup, &lt;a href=&quot;https://infinitediaries.net/my-2020-hackintosh-hardware-spec/&quot;&gt;this one&lt;/a&gt; being the last I read.&lt;/p&gt;

&lt;h2 id=&quot;social-time&quot;&gt;Social time&lt;/h2&gt;

&lt;p&gt;I used to spend a lot of time hanging out with my coworkers when I was working for Telefónica. The company
itself (Telefónica R&amp;amp;D) was around 1000 employees back then, and over the ten years I worked there I had the chance
to meet a lot of great people.
In my last role in the company I was leading a 30 members team in an organization of around 150, which meant
a lot of interactions, both professional and personal ones. When I left the company almost three years ago,
I thought the social part was going to be one the things I’d miss the most, and looking back that’s been the case.
It was very common for me to hang out in a coffee break, lunch time or after work with a beer, and I do miss that!
Nevertheless I’ve done several activities I would not have done if I continued working there, like joining a triathlon club (even though
I don’t swim, that’s an opportunity to hang out with runners and riders :-)), attending a japanese food course or taking some painting
classes (not very impressing results, as you can see :blush:).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/painting.jpg&quot; alt=&quot;Not very impressing results!&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;family-time&quot;&gt;Family time&lt;/h2&gt;

&lt;p&gt;It’s not something that I knew would happen when I started working remotely, but my daughter was born a couple of months ago, one of the best things ever happened to me.
After some weeks of parental leave, I’ve got back to work. Knowing that I’m 30 seconds away from her really makes me happier.&lt;/p&gt;

&lt;h2 id=&quot;avoid-interruptions&quot;&gt;Avoid interruptions&lt;/h2&gt;
&lt;p&gt;Working in an office usually means you’d get tons of interruptions during a day, specially if you’re working in an open space.
Working from home does not mean you won’t have any interruptions, but you can probably impact better manage those and get rid of them with ease.&lt;/p&gt;

&lt;h2 id=&quot;flexible-working-hours-but-limit-them&quot;&gt;Flexible working hours, but limit them&lt;/h2&gt;

&lt;p&gt;Working from home means it’s much simpler to change my working hours, and having that flexibility is great for those days
when something requires my attention, or just it’s 12PM, it’s sunny and I’m willing to run for a while.&lt;/p&gt;

&lt;p&gt;I’ve been using several daily schedules, and the one that currently works better for me is:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;start working early in the morning (7 AM): that’s a requirement because our company is not only fully remote but also fully distributed. We have people
 in San Francisco, Sydney, Perth and Barcelona. While most of our work is asynchronous, having a daily standup helps us to sync up and hang out a bit.&lt;/li&gt;
  &lt;li&gt;take a long break at noon: something like 3-4 hours, so I can spend some time with the family, do my almost daily run routine while training for the next marathon and even take a short power nap.&lt;/li&gt;
  &lt;li&gt;work another 4-5 hours in the afternoon: key to overlap with PST timezone and catch up with the team.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Well, this is the theory of this, reality comes with longer hours at work although I am working to improve the routine :blush:.&lt;/p&gt;

&lt;p&gt;If you want to take a single advice: if you are working from home, &lt;strong&gt;try to identify burnout symptoms and take actions&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;technology--tools&quot;&gt;Technology / Tools&lt;/h2&gt;
&lt;p&gt;These are the tools we’re using for our day 2 day work:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://jamm.app&quot;&gt;Jamm&lt;/a&gt;: Jamm is a video-first collaboration experience for modern teams. Remember the note at the beginning of this post, that’s the product we’re building.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://slack.com/&quot;&gt;Slack&lt;/a&gt;: for internal communication we don’t use email, hence we’re using Slack for any text-based communication. We also use Slack as an information hub
(integrations with our cloud provider, Typeform, source code, ticketing tool, etc).&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://notion.so&quot;&gt;Notion&lt;/a&gt;: internal documentation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;communication-and-expectations&quot;&gt;Communication and expectations&lt;/h2&gt;

&lt;p&gt;Proactive communication is a key skill if you work in a physical office with your team, but it’s even more relevant when working away.
To keep the team up to speed, and mitigate the effect of  working in different timezones, prior to calling it day I share my notes with the rest on how the day went, issues I had or just the last joke I’ve heard around…&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Under promise and over deliver&lt;/strong&gt; is a well known quote, I’d reformulate to &lt;strong&gt;over and over communicate&lt;/strong&gt; if you’re working remotely.&lt;/p&gt;

&lt;h2 id=&quot;work-from-anywhere&quot;&gt;Work from anywhere&lt;/h2&gt;
&lt;p&gt;One of the key benefits of remote work is that I can work from anymore, given
that what I just need is my computer and a good Internet connection. Why should
I be limiting myself to be in my home office?&lt;/p&gt;

&lt;h2 id=&quot;so-whats-the-deal&quot;&gt;So what’s the deal?&lt;/h2&gt;

&lt;p&gt;According to &lt;a href=&quot;https://lp.buffer.com/state-of-remote-work-2020&quot;&gt;State of remote work analysis by Buffer and AngelList&lt;/a&gt;, 98% of the 
surveyed would like to work remotely, ast least some of the time, for the rest of their career.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://uploads-ssl.webflow.com/5d60176738c00e7ae2afeba2/5e3d8ed566a9ae6efd17c61d_work-remotely-rest-of-career%402x.png&quot; alt=&quot;Sate of remote report 2020&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And I don’t blame them! While working remotely may have some negative consequences like not being able to unplug or feeling 
disconnected from the team, you can impact on these consequences by building a company culture around remote work and your own experience as you gain it.&lt;/p&gt;

&lt;p&gt;In my experience, the flexibility to work in a flexible schedule and from anywhere are the major advantages, something I’d definitely
try to keep at least for some years :hammer:&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Debug a Node.js app transpiled with Babel and running in Docker from VSCode</title>
   <link href="http://juandebravo.com/2019/05/20/debug-node-babel-docker/"/>
   <updated>2019-05-20T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2019/05/20/debug-node-babel-docker/</id>
   <content type="html">&lt;p&gt;I’ve been playing lately with the technologies pointed out in the post title, and it took me
a considerable amount of time to be able to debug it with ease. I went through
&lt;a href=&quot;https://michele.io/nodemon-babel-vscode/&quot;&gt;several&lt;/a&gt; &lt;a href=&quot;https://github.com/Microsoft/vscode-recipes/issues/127&quot;&gt;pages&lt;/a&gt;
tackling these technologies together, but none of them was specific enough for me to get the setup working;
hence I’ve decided to describe the steps I took, in case this is helpful to anyone fighting
against technology.&lt;/p&gt;

&lt;p&gt;Through this post I’ll describe the different pieces and introducing some snippets of code / configuration,
but in case you prefer to get the whole picture you can &lt;a href=&quot;https://github.com/juandebravo/setup-node-babel-docker-vscode&quot;&gt;clone the sample project that describes the setup&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;description&quot;&gt;Description&lt;/h2&gt;

&lt;p&gt;I want to debug a Node.JS application that is:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;written using latest version of JavaScript, concretely using &lt;strong&gt;JS modules&lt;/strong&gt;, which is part of ES6 (ECMAScript 2015) standard:
I prefer using ES modules (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;import&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;export&lt;/code&gt; statements) instead of CommonJS &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;require&lt;/code&gt; spec, so the code is written
using a similar structure as web code.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://babeljs.io/&quot;&gt;transpiled using &lt;strong&gt;Babel&lt;/strong&gt;&lt;/a&gt;: current versions of Node do not support natively ES6 modules (only through experimental
flags), hence it’s required to transpile the source code to code that can be executed in Node (10.15) runtime.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;executed as a &lt;a href=&quot;https://www.docker.com/&quot;&gt;&lt;strong&gt;Docker container&lt;/strong&gt;&lt;/a&gt;: my usual preference for running applications.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My current IDE of choice is &lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;&lt;strong&gt;VS Code&lt;/strong&gt;&lt;/a&gt;, so the expectation is to be able to define a break point in the IDE, connect the
debugger to a running container and intercept any request going through the break point.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/es6-node-docker-vscode/global-picture.png&quot; alt=&quot;Several pieces moving around&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;technical-pieces&quot;&gt;Technical pieces&lt;/h2&gt;

&lt;h3 id=&quot;babel&quot;&gt;Babel&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://babeljs.io/&quot;&gt;Babel&lt;/a&gt; is an impressive project that helps you run the latest functionalities of JavaScript in any runtime. It makes
it happen by compiling down features unsupported by your JS runtime to a supported version.&lt;/p&gt;

&lt;p&gt;When using Babel, you need to compile the source code before executing your application. In the &lt;a href=&quot;https://github.com/juandebravo/setup-node-babel-docker-vscode&quot;&gt;sample project&lt;/a&gt;
there are a couple of npm scripts to launch the application (or just run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make run&lt;/code&gt; in the root folder):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;build&lt;/strong&gt;: executes babel to compile the source code.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;serve&lt;/strong&gt;: launch the application using the compiled code generated by Babel (&lt;em&gt;dist&lt;/em&gt; folder).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Babel functionality is based on composition, so the developer can choose which functionalities are required for the project
and install the specific NPM packages (instead of integraging a huge framework). In the sample project this is the bare minimum
list of Babel dependencies:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;@babel/core&lt;/strong&gt;: basic functionality, which depends on the project configuration defined in the &lt;em&gt;.babelrc&lt;/em&gt; file.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;@babel/cli&lt;/strong&gt;: used to compile from command line instead of loading a library.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;@babel/preset-env&lt;/strong&gt;: defines automatically the required plugins/polyfills based on the runtime defined.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nevertheless, when you are under development you want your changes to be refreshed as soon as possible, either for running unit
tests or for validating the changes manually. Here is where &lt;a href=&quot;https://babeljs.io/docs/en/babel-node&quot;&gt;&lt;strong&gt;babel-node&lt;/strong&gt;&lt;/a&gt; package appears: it works similar to
Node.js command line, but has a pre-step that executes the Babel compilation. This simplifies a lot the hot-reloading process.&lt;/p&gt;

&lt;h3 id=&quot;sourcemaps&quot;&gt;Sourcemaps&lt;/h3&gt;

&lt;p&gt;The JavaScript code to be executed in the Docker container would differ from the source code itself due to the compilation
phase.&lt;/p&gt;

&lt;p&gt;However, as a developer you want to define a breakpoint while debugging in the original source code, as it’s loaded in your
IDE (VS Code in this case).&lt;/p&gt;

&lt;p&gt;This is where a source map comes into the scene, as it maps the compiled code to the original one, creating a way to
reconstruct the source code.&lt;/p&gt;

&lt;p&gt;Babel can be configured to generate source maps both from the CLI (&lt;em&gt;–source-maps&lt;/em&gt; flag) or in the configuration file (&lt;em&gt;.babelrc&lt;/em&gt;).
Keep in mind though that &lt;a href=&quot;https://github.com/babel/babel/issues/2484&quot;&gt;its support in config file is limited&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;docker&quot;&gt;Docker&lt;/h3&gt;

&lt;p&gt;Upon launching the VS Code debugger, it will open a connection to the machine where the application is running. By default the
port where the Node application listens is 9229, hence it’s important to map this port from the container to localhost
so VS Code can connect to it.&lt;/p&gt;

&lt;h3 id=&quot;nodemon&quot;&gt;Nodemon&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://nodemon.io/&quot;&gt;Nodemon&lt;/a&gt; is a utility that monitors for any changes in the predefined paths (the source code path) and automatically
restarts the application. It’s installed as a development dependency via NPM.&lt;/p&gt;

&lt;p&gt;Nodemon will run inside the Docker container, so for Nodemon to detect changes in the source code it’s important to mount
a volume in the container to map the source code from the host to the container.&lt;/p&gt;

&lt;h3 id=&quot;vscode&quot;&gt;VSCode&lt;/h3&gt;

&lt;p&gt;VSCode provides several ways to debug a program. In this case, we’re interested in attaching to a process that is running
in a remote host (a Docker container) through a local binding (port 9229, as described before).
Upon adding a debug configuration, file &lt;em&gt;.vscode/launch.json&lt;/em&gt; will be updated with the new entry. It’s important to configure
the attributes that defines the local and remote source code root path, as well as the source maps location.&lt;/p&gt;

&lt;p&gt;Defining properly the VS Code launch configuration was only of the hardest points; if you’re having issues &lt;a href=&quot;https://github.com/juandebravo/setup-node-babel-docker-vscode/blob/master/.vscode/launch.json&quot;&gt;check my
configuration in the sample project&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/juandebravo/setup-node-babel-docker-vscode&quot;&gt;sample project&lt;/a&gt; includes any configuration required for the setup.&lt;/p&gt;

&lt;p&gt;These are the big parts:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;babel&lt;/strong&gt;: several modules installed via &lt;em&gt;NPM&lt;/em&gt; (&lt;em&gt;package.json&lt;/em&gt;). It’s configuration relies on &lt;em&gt;.babelrc&lt;/em&gt; file.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;babel-node&lt;/strong&gt;: it transpiles and executes the code. Any CLI argument provided to &lt;em&gt;babel-node&lt;/em&gt; is forwarded to Node, so it’s
important to include the flag &lt;em&gt;–inspect&lt;/em&gt; to activate the inspector.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;nodemon&lt;/strong&gt;: used in NPM script &lt;em&gt;start&lt;/em&gt; for hot-reloading the application.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;docker&lt;/strong&gt;: important to expose the debugging port (&lt;em&gt;9229&lt;/em&gt;) and mount the source code folder from the host.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Makefile&lt;/strong&gt;: execute the target &lt;em&gt;debug&lt;/em&gt; for running the application listening in the debug port and ready for hot-reloading.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;VS Code&lt;/strong&gt;: Debug configuration in &lt;em&gt;.vscode/launch.json&lt;/em&gt; file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you have defined a breakpoint in your code in VS Code:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;launch the Docker container executing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make debug&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;launch VS Code debugger.&lt;/li&gt;
  &lt;li&gt;You should see a &lt;em&gt;Debugger attached&lt;/em&gt; log in the Docker logs stdout logs:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/es6-node-docker-vscode/debugger.png&quot; alt=&quot;Debugger attached&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Launch a request that goes through your breakpoint.&lt;/li&gt;
  &lt;li&gt;VS Code stops in your breakpoint.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enjoy :-)&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>How to skip a subfolder while mounting a volume in Docker</title>
   <link href="http://juandebravo.com/2019/04/25/docker-mount-volume-skip-subfolder/"/>
   <updated>2019-04-25T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2019/04/25/docker-mount-volume-skip-subfolder/</id>
   <content type="html">&lt;p&gt;When working in a containers based environment, it’s very frequent to build Docker images that
are agnostic to the environment. That way, they can be deployed in any environment, from local
development to production, which gives the great advantage of preventing any change in a Docker
image taht was certified internally in a testing/staging environment for deploying it into
production.&lt;/p&gt;

&lt;p&gt;However, this may create an issue while developing, where you want to test your changes as soon
as possible, hence it’s convenient to skip creating a new Docker image every time a change in the
source code is detected.&lt;/p&gt;

&lt;p&gt;A common pattern is to run locally a Docker container mounting the folder where your source code is
located into the folder where it’s included while generating the Docker image (assuming there’s no
compilation / packaging / etc for going straight into the point :) ).&lt;/p&gt;

&lt;p&gt;For example, let’s assume a &lt;em&gt;Node.js application&lt;/em&gt; that keeps the source code in the root folder of
the repository in the host machine and that copies it into the
&lt;em&gt;/usr/src/app&lt;/em&gt; folder of the Docker image. Mounting the source code folder can be accomplished
with the following command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker run -v $(PWD):/usr/src/app my-app:latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;While this is very straight forward, it may create a big issue, as you &lt;strong&gt;don’t want, at all,
to mount your node_modules subfolder into the Docker container&lt;/strong&gt;. Some dependencies
might require native code/compilation, and if your host machine does not match the one used in the
Docker image, you’d get into troubles.&lt;/p&gt;

&lt;p&gt;To prevent this, a special volume option pointing to the &lt;em&gt;node_modules subfolder&lt;/em&gt; can be included,
and this folder won’t be overwritten by the host information:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker run \
  -v $(PWD):/usr/src/app \
  -v /usr/src/app/node_modules \
  my-app:latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Continuous Delivery to Google K8s Engine using Travis</title>
   <link href="http://juandebravo.com/2019/03/01/travis-google-kubernetes-engine-deployment/"/>
   <updated>2019-03-01T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2019/03/01/travis-google-kubernetes-engine-deployment/</id>
   <content type="html">&lt;p&gt;When you start a new project one of the key points to tackle and nail down
is how to automate the recurrent tasks you will be facing frequently, being
those tasks mainly around continuous integration and deployment.
Small investments in time around automation at the beginning (or at any time)
will pay off very quickly.&lt;/p&gt;

&lt;p&gt;In a side project I’ve been working on over the last weeks, we chose
&lt;a href=&quot;https://travis-ci.org/&quot;&gt;&lt;strong&gt;Travis CI&lt;/strong&gt;&lt;/a&gt; for Continuous Integration
and &lt;a href=&quot;https://cloud.google.com/kubernetes-engine/&quot;&gt;&lt;strong&gt;Google Kubernetes Engine&lt;/strong&gt;&lt;/a&gt;
for building our production environment (very optimistic to call it &lt;em&gt;production&lt;/em&gt;
at our stage).&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://docs.travis-ci.com/user/tutorial/&quot;&gt;Travis official documentation&lt;/a&gt; describes
with detail how to set up your project for running tests, being them either unit or acceptance,
upon opening a Pull Request in GitHub or committing a change to a specific branch.&lt;/p&gt;

&lt;p&gt;On the other hand, Google Cloud documentation includes a detailed example about how to
implement &lt;a href=&quot;https://cloud.google.com/solutions/continuous-delivery-with-travis-ci&quot;&gt;continuous delivery to App Engine using
Travis CI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;However, I could not find any official documentation, blog post or even StackOverflow
thread describing how to configure Travis for deploying a change to Google
Kubernetes Engine when the integration phase ends with success. So this is what this post is about.&lt;/p&gt;

&lt;h1 id=&quot;the-goal&quot;&gt;The goal&lt;/h1&gt;

&lt;p&gt;The picture below describes what I was aiming for (remember that I’m putting aside
the Continuous Integration workflow):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/travis-google-kubernetes/travis-gke.png&quot; alt=&quot;Continuous Delivery to Google Kubernetes Engine&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I’ve created this &lt;a href=&quot;https://github.com/juandebravo/travis-google-kubernetes-engine&quot;&gt;Github repo&lt;/a&gt; as
an example. It may be useful for you in case you are considering to implement this workflow; if that’s
the case, remember to update the configuration in the
&lt;a href=&quot;https://github.com/juandebravo/travis-google-kubernetes-engine/blob/master/Makefile&quot;&gt;Makefile&lt;/a&gt;
with your Google Cloud data. If you’re already familiar with Travis and Google Cloud, you may skip
the rest of the post and go directly to that repository.&lt;/p&gt;

&lt;h1 id=&quot;setting-up-travis&quot;&gt;Setting up Travis&lt;/h1&gt;

&lt;p&gt;Travis setup is configured in the &lt;a href=&quot;https://travis-ci.com/getting_started&quot;&gt;.travis.yml&lt;/a&gt; file, that should
be part of the repository that keeps your source code. In this chapter we’ll go through the main
aspects to consider for our scenario.&lt;/p&gt;

&lt;p&gt;Even though we want to deploy the new version whenever there’s a new change in &lt;em&gt;master branch&lt;/em&gt;, we should
do that &lt;em&gt;only if&lt;/em&gt; the unit/integration testing phase ends successfully. Following &lt;a href=&quot;https://docs.travis-ci.com/user/job-lifecycle/&quot;&gt;Travis job cycle
documentation&lt;/a&gt;, the configuration to achieve that is
the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;branches -&amp;gt; only&lt;/em&gt;: set this configuration to &lt;em&gt;master&lt;/em&gt;:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;branches:
  only:
  - master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;after_success&lt;/em&gt;: define the script that will tackle the deployment to GKE. We use &lt;a href=&quot;https://docs.travis-ci.com/user/environment-variables/&quot;&gt;Travis automatic
env variables&lt;/a&gt; to ensure we don’t deploy a new
version in case of the event being associated to a new Pull Request.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Deploy web version to Google Kubernetes Engine
after_success:
- if [ &quot;$TRAVIS_PULL_REQUEST&quot; == &quot;false&quot; ]; then ./deploy-web.sh; fi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Another relevant point is to enable &lt;em&gt;Docker as a service&lt;/em&gt;, as we need to build a Docker image and push it
to Docker registry.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;services:
- docker
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/juandebravo/travis-google-kubernetes-engine/blob/master/.travis.yml&quot;&gt;Here&lt;/a&gt;
you can find the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.travis.yml&lt;/code&gt; from the example.&lt;/p&gt;

&lt;h1 id=&quot;setting-up-google-cloud&quot;&gt;Setting up Google Cloud&lt;/h1&gt;

&lt;p&gt;This guide assumes you already have a Google Cloud project running a &lt;a href=&quot;https://cloud.google.com/kubernetes-engine/&quot;&gt;Kubernetes
Engine&lt;/a&gt; cluster.&lt;/p&gt;

&lt;h2 id=&quot;storage&quot;&gt;Storage&lt;/h2&gt;

&lt;p&gt;In order to be able to deploy a new workload to Kubernetes, it’s required to push the relevant
Docker images to a &lt;a href=&quot;https://docs.docker.com/registry/&quot;&gt;Docker registry&lt;/a&gt;, that will be used by
Kubernetes do pull them.&lt;/p&gt;

&lt;p&gt;Even though we could use &lt;a href=&quot;https://hub.docker.com/&quot;&gt;Docker hub&lt;/a&gt; for that, we will use &lt;a href=&quot;https://cloud.google.com/container-registry/docs/&quot;&gt;Google Container
Registry&lt;/a&gt;. This means we’ll need to
grant to our script running in Travis permissions to get access to &lt;strong&gt;Google Storage&lt;/strong&gt;, as this is
the infrastructure where Container Registry stands.&lt;/p&gt;

&lt;h2 id=&quot;create-service-account-and-key-associated-to-it&quot;&gt;Create Service account and key associated to it&lt;/h2&gt;

&lt;p&gt;In order to deploy a new version from Travis to Google Cloud, we need to create a service account that
enables the &lt;em&gt;Cloud SDK&lt;/em&gt; (installed in our Travis environment, as we’ll see) to authenticate with
our Google Cloud project.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;In the Google Cloud Project Console, open the &lt;em&gt;IAM &amp;amp; admin&lt;/em&gt; page.&lt;/li&gt;
  &lt;li&gt;Go to &lt;em&gt;Service accounts&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;Click &lt;em&gt;Create Service Account&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;Enter a Service account name, such as &lt;em&gt;continuous-delivery-from-travis&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;Include a description for the account.&lt;/li&gt;
  &lt;li&gt;Click Create.&lt;/li&gt;
  &lt;li&gt;In the &lt;em&gt;Service account permissions&lt;/em&gt; select box, select the following roles:
    &lt;ul&gt;
      &lt;li&gt;&lt;em&gt;Kubernetes Engine -&amp;gt; Kubernetes Engine Developer&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;Storage -&amp;gt; Storage Admin&lt;/em&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Click Create.&lt;/li&gt;
  &lt;li&gt;Click Create Key, choose &lt;em&gt;JSON&lt;/em&gt; as Key type and press Create. A JSON file containing the generated key is downloaded to your computer.&lt;/li&gt;
  &lt;li&gt;Click Done.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;define-your-strategy-for-making-available-the-service-account-key-in-travis&quot;&gt;Define your strategy for making available the Service Account Key in Travis&lt;/h1&gt;

&lt;p&gt;Key management is a top priority task from security point of view for any project, and good news is
that any cloud provider gives you a solid solution for secrets management. I’m not tackling this
point in this article, but the as this article is related to Travis and Google Cloud,
those two links are the key entry points for the subject:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://cloud.google.com/solutions/secrets-management/&quot;&gt;Travis encryption files&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://cloud.google.com/solutions/secrets-management/&quot;&gt;Google Cloud Secrets management&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;deployment-script&quot;&gt;Deployment script&lt;/h1&gt;

&lt;p&gt;Now that we’ve Travis and Google Cloud configured, the last point to address is the script that will
deploy the latest version of our software to our Kubernetes cluster. The script should:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Use &lt;a href=&quot;https://cloud.google.com/sdk/gcloud/&quot;&gt;gcloud command-line tool&lt;/a&gt; to connect to Google Cloud.&lt;/li&gt;
  &lt;li&gt;Ensure &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kubectl&lt;/code&gt; is available.&lt;/li&gt;
  &lt;li&gt;Authenticate against Google Cloud (using the key we generated and encrypted in previous steps).&lt;/li&gt;
  &lt;li&gt;Configure the project, Kubernetes cluster and Docker registry.&lt;/li&gt;
  &lt;li&gt;Build Docker images.&lt;/li&gt;
  &lt;li&gt;Push Docker images to Docker registry.&lt;/li&gt;
  &lt;li&gt;Deploy to Kubernetes cluster.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/juandebravo/travis-google-kubernetes-engine/blob/master/deploy.sh&quot;&gt;This bash script&lt;/a&gt;
covers the steps above for the example repo.&lt;/p&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;Using Travis for Continuous Delivery to a Google Cloud Kubernetes Engine is quite straight forward… as
long as you’re familiar with both tools :rocket:.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>I have just deleted my Facebook account</title>
   <link href="http://juandebravo.com/2018/12/26/I-have-just-deleted-my-facebook-account/"/>
   <updated>2018-12-26T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2018/12/26/I-have-just-deleted-my-facebook-account/</id>
   <content type="html">&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: I’ve just deleted my Facebook account, and you should think about it as well.&lt;/p&gt;

&lt;p&gt;I removed my Facebook application from my mobile device about a year ago.&lt;/p&gt;

&lt;p&gt;My personal journey started some months or years before, after reading
&lt;a href=&quot;https://www.goodreads.com/book/show/9484114-the-happiness-advantage&quot;&gt;The Happiness Advantage&lt;/a&gt;,
recommended by my friend &lt;a href=&quot;https://twitter.com/ShaykeC&quot;&gt;Shay Cohen&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Back then, I had a very bad habit in regards to how I managed my professional email. Lot of discussions
and topics were going on via email (pre-Slack times :)), and I was checking it from my mobile as soon
as I had the minimum spare time: waiting for the metro, having breakfast, walking… and more problematic:
right before going to sleep and right after waking up.&lt;/p&gt;

&lt;p&gt;Shay explains in &lt;a href=&quot;https://medium.com/@shaycohen/how-to-replace-a-bad-habit-with-good-one-how-i-stopped-drinking-coke-zero-d892e2bbe69f&quot;&gt;this post&lt;/a&gt;
how difficult breaking a bad habit is. In my case, for breaking my toxic habit I decided to
remove my professional email account from my mobile before going on holidays, and more importantly,
don’t reconfigure it when I got back to work. That was my personal deal and I succeeded on keeping it.
At the beginning I was feeling bad and taking it as an unprofessional behavior. I &lt;em&gt;just&lt;/em&gt; needed to realize
that nobody is getting paid just by managing emails from a specific device, so eventually I
felt ok and I never reconfigured it again on my mobile.&lt;/p&gt;

&lt;p&gt;Fast forward some months, same thing was happening with Facebook (I was checking Facebook as soon as I had
30 seconds). Now that I already knew the solution, I just removed the application.&lt;/p&gt;

&lt;p&gt;This was before &lt;a href=&quot;https://www.nytimes.com/2018/04/04/us/politics/cambridge-analytica-scandal-fallout.html&quot;&gt;the first of a series of scandals&lt;/a&gt; related to Facebook
data usage.&lt;/p&gt;

&lt;p&gt;Since then, I’ve accessed Facebook via the web interface only from time to time (maybe once every three months).
During these months, the only functionality I’ve kept using is the friends’ birthdays reminder (automatic email
sent by Facebook).&lt;/p&gt;

&lt;p&gt;Last news about &lt;a href=&quot;https://www.nytimes.com/2018/12/18/technology/facebook-privacy.html&quot;&gt;the social network&lt;/a&gt; have
acted as the required trigger for me to delete my Facebook account. If you’re interested in how Facebook
online advertising business works and their usage in regards to personal information, I recommend &lt;a href=&quot;https://medium.com/@danielcoloma/facebook-and-your-personal-data-77925739ddc1&quot;&gt;this post&lt;/a&gt; by &lt;a href=&quot;https://twitter.com/danielcoloma&quot;&gt;Daniel Coloma&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So next step for me was deleting my Facebook account. &lt;a href=&quot;https://www.nytimes.com/2018/10/10/technology/personaltech/how-to-delete-facebook-instagram-account.html&quot;&gt;This article by New York Times&lt;/a&gt;
describes pretty well how to do it. &lt;strong&gt;&lt;a href=&quot;https://twitter.com/search?q=%23DeleteFacebook&amp;amp;src=typd&quot;&gt;#DeleteFacebook&lt;/a&gt;&lt;/strong&gt;
movement has been around for some time, and even
&lt;a href=&quot;https://www.forbes.com/sites/parmyolson/2018/09/26/exclusive-whatsapp-cofounder-brian-acton-gives-the-inside-story-on-deletefacebook-and-why-he-left-850-million-behind/#2f393aa93f20&quot;&gt;Brian Actor, WhatsApp cofounder, stepped in to it some months ago&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I downloaded my Facebook personal data in JSON format instead of HTML, so it’s easier to work with it in case I need to.&lt;/p&gt;

&lt;p&gt;Some points about the downloaded data:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;it’s very well organized by functionality in separated folders.&lt;/li&gt;
  &lt;li&gt;it provides accurate data about &lt;em&gt;when&lt;/em&gt; things happened in your social network.&lt;/li&gt;
  &lt;li&gt;some folders contain a file with invalid JSON format, as it contains a file with content &lt;em&gt;You have no data in this section&lt;/em&gt; but without double quotes, hence it’s not a valid JSON string field.&lt;/li&gt;
  &lt;li&gt;it misses relevant information for me, like birthday events.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In case you also want to download your friends’ birthdays information, just follow &lt;a href=&quot;https://www.facebook.com/help/152652248136178/&quot;&gt;these steps&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Bye bye Facebook. You were great in the past and hopefully you will seek and find another way to make business, so you can
be trustworthy again.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>How to sign a commit in git with a GPG key</title>
   <link href="http://juandebravo.com/2018/12/02/sign-your-git-commits-with-gpg/"/>
   <updated>2018-12-02T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2018/12/02/sign-your-git-commits-with-gpg/</id>
   <content type="html">&lt;p&gt;In git, whenever you want to add a change to a repository, a new &lt;a href=&quot;https://git-scm.com/docs/git-commit&quot;&gt;commit&lt;/a&gt; is created in the repository history.&lt;/p&gt;

&lt;p&gt;Besides the actual changes in the repository, every commit includes several metadata fields,
some of them pointing to both the author and the committer:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;Author&lt;/em&gt;: the person who wrote the code.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Committer&lt;/em&gt;: the person who added the code to the repository.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    Author:     juandebravo &amp;lt;juandebravo@gmail.com&amp;gt;
    AuthorDate: Wed Nov 21 22:41:04 2018 +0100
    Commit:     juandebravo &amp;lt;juandebravo@gmail.com&amp;gt;
    CommitDate: Wed Nov 21 22:41:04 2018 +0100
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;99% of the times, both author and committer points to the same person; only in distributed teams working
in a flow that requires both &lt;a href=&quot;https://git-scm.com/docs/git-format-patch&quot;&gt;&lt;em&gt;git format-patch&lt;/em&gt;&lt;/a&gt;
and &lt;a href=&quot;https://git-scm.com/docs/git-apply&quot;&gt;&lt;em&gt;git apply&lt;/em&gt;&lt;/a&gt; may happen that author and committer
are different (e.g. someone providing a new functionality or bug fix, the author, but not having write
permissions in the repository and therefore another person, the committer, would write the commit
on his/her behalf).&lt;/p&gt;

&lt;p&gt;Both fields are configurable locally, and there’s no way you can ensure a commit uploaded to
a repository hosted in a SaaS product like Github or Gitlab was authored or committed by the person
defined in &lt;em&gt;Author&lt;/em&gt; and &lt;em&gt;Committer&lt;/em&gt; fields… unless you enter &lt;strong&gt;commit signature verification&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Git provides a mechanism to &lt;a href=&quot;https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work&quot;&gt;sign your work with a GPG key&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Working on my macOS High Sierra, these are the steps I followed to get my commits signed:&lt;/p&gt;

&lt;h4 id=&quot;install-git-and-gnupg&quot;&gt;Install git and gnupg&lt;/h4&gt;

&lt;!-- https://stackoverflow.com/questions/39494631/gpg-failed-to-sign-the-data-fatal-failed-to-write-commit-object-git-2-10-0 --&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;git gnupg gpg-agent pinentry-mac
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;pinentry-program /usr/local/bin/pinentry-mac&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.gnupg/gpg-agent.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;generate-a-gpg-key&quot;&gt;Generate a GPG key&lt;/h4&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gpg &lt;span class=&quot;nt&quot;&gt;--gen-key&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Important&lt;/em&gt;: include the email and user name you’d like to use while signing your commits.&lt;/p&gt;

&lt;h4 id=&quot;obtain-the-gpg-key-id-of-the-key-you-just-generated&quot;&gt;Obtain the GPG key id of the key you just generated&lt;/h4&gt;

&lt;p&gt;You will need this number in the following step.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gpg &lt;span class=&quot;nt&quot;&gt;--list-secret-keys&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--keyid-format&lt;/span&gt; LONG
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;configure-username-email-and-gpg-in-git&quot;&gt;Configure username, email and GPG in git&lt;/h4&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; user.name &amp;lt;your-user-name&amp;gt;
git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; user.email &amp;lt;your-email&amp;gt;
git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; gpg.program gpg
git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; commit.gpgsign &lt;span class=&quot;nb&quot;&gt;true
&lt;/span&gt;git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; user.signingkey &amp;lt;your-gpg-key-id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;restart-gpg-agent&quot;&gt;Restart GPG agent&lt;/h4&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gpgconf &lt;span class=&quot;nt&quot;&gt;--kill&lt;/span&gt; gpg-agent
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;github&quot;&gt;Github&lt;/h2&gt;
&lt;p&gt;Once you start signing your commits, you can let the world know commits pointing to your username in
&lt;a href=&quot;https://help.github.com/articles/associating-an-email-with-your-gpg-key/&quot;&gt;GitHub&lt;/a&gt; were indeed
committed by you (or at least by someone with access to your GPG private key!).&lt;/p&gt;

&lt;p&gt;First of all, export the public key to ASCII armor format:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gpg &lt;span class=&quot;nt&quot;&gt;--armor&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--export&lt;/span&gt; GPG &amp;lt;your-gpg-key-id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Second step is uploading the public key using &lt;a href=&quot;https://github.com/settings/keys&quot;&gt;your GitHub key settings page&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Click on &lt;em&gt;New GPG key&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Add the GPG public key ASCII representation&lt;/li&gt;
  &lt;li&gt;Click on &lt;em&gt;Add GPG key&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Since now on, your commits will be labeled with &lt;strong&gt;[Verified]&lt;/strong&gt; in GitHub repository history page&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/sign-git-commits/verified-commit.png&quot; alt=&quot;Sign git commit&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Python 3.7: StopIteration could be your next headache</title>
   <link href="http://juandebravo.com/2018/11/09/python-37-stop-iteration/"/>
   <updated>2018-11-09T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2018/11/09/python-37-stop-iteration/</id>
   <content type="html">&lt;p&gt;I upgraded the python interpreter in one of the components I ran in production
from 3.5 to 3.7. Main reason for that was testing &lt;a href=&quot;https://docs.python.org/3/library/dataclasses.html&quot;&gt;&lt;strong&gt;dataclasses&lt;/strong&gt;&lt;/a&gt; functionality. Sometime ago
I &lt;a href=&quot;https://www.juandebravo.com/2014/01/04/python-auto-initializer/&quot;&gt;wrote a post&lt;/a&gt;
about how to build a simply automatic initializer, and eventually it’s implemented
in the standard library, which I believe is a great new feature!&lt;/p&gt;

&lt;p&gt;The upgrade was quite smooth, even though I had an issue due to a non backwards
compatible change in how a generator should flag it’s exhausted.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Making a long story short&lt;/em&gt;: use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;return&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StopIteration&lt;/code&gt; when you want
to stop sending items from your generator.&lt;/p&gt;

&lt;p&gt;Next is the &lt;em&gt;long story&lt;/em&gt;, things I learned while investigating the issue and
the reason why I didn’t capture it before hand.&lt;/p&gt;

&lt;h2 id=&quot;lesson-1-read-the-release-notes&quot;&gt;Lesson 1: Read the release notes&lt;/h2&gt;

&lt;p&gt;This may sound obvious, but…&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Remember, a few hours of trial and error can save you several minutes
of looking at the README.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://twitter.com/iamdevloper/status/1060067235316809729&quot;&gt;I am devloper (7 Nov 2018)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://docs.python.org/3/whatsnew/3.7.html&quot;&gt;Python 3.7 release notes&lt;/a&gt; explains
very clearly &lt;a href=&quot;https://docs.python.org/3/whatsnew/3.7.html#changes-in-python-behavior&quot;&gt;changes that this new version brings into python behavior&lt;/a&gt;, being one
of them &lt;a href=&quot;https://www.python.org/dev/peps/pep-0479/&quot;&gt;PEP-479&lt;/a&gt;. This PEP introduces a
non backwards compatible change in how a generator behaves.&lt;/p&gt;

&lt;p&gt;I was so focused on the new feature I wanted to test, I didn’t go over the
release notes.&lt;/p&gt;

&lt;h2 id=&quot;lesson-2-the-process&quot;&gt;Lesson 2: The process&lt;/h2&gt;

&lt;p&gt;When you have a containerized environment, it’s quite straight forward
to change/upgrade a specific component execution platform. We’ve been
using Python 3.5 as our default runtime for a while, but I was intrigued
to upgrade to newest versions and check the new functionalities provided
by the language.&lt;/p&gt;

&lt;p&gt;To be specific, I read some months ago about &lt;a href=&quot;https://docs.python.org/3/library/dataclasses.html&quot;&gt;&lt;em&gt;dataclasses&lt;/em&gt;&lt;/a&gt; and really looked to
me like a nice functionality to reduce boilerplate code. Also, &lt;a href=&quot;https://docs.python.org/3/whatsnew/3.7.html#whatsnew37-pep563&quot;&gt;PEP563 -
Postponed evaluation of annotations&lt;/a&gt;
is a great new feature, in case you’re using annotations in your code.&lt;/p&gt;

&lt;p&gt;In order to test the python interpreter upgrade, I chose as candidate an
offline component which main goal is accessing gDrive API. Our library implements
a tiny wrapper over &lt;a href=&quot;https://developers.google.com/api-client-library/python/start/get_started&quot;&gt;the official python client library&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Find below a simplified snippet that, given a gDrive folderId, returns a generator
which includes every file under that folder. As filenames are returned in several
pages to prevent a very long response, we prefer using a generator instead
of a list, so it’s up to the client to iterate as much as it’s needed (and therefore
request additional pages under the hood):&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_files_in_folder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;folder_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;next_page_token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Request a page
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;_files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;next_page_token&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_get_files_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;folder_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;next_page_token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Return every file included in the results
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;next_page_token&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Flag generator is exhausted
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;StopIteration&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Request next page
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_files_in_folder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;folder_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;next_page_token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next_page_token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_get_files_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;folder_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;page_token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;pageSize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;pageToken&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;page_token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;fields&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;files(id,name),incompleteSearch,kind,nextPageToken&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&apos;{0}&apos; in parents&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;folder_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;files&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;nextPageToken&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Right, probably raising a StopIteration instead of simply return was not a good idea, but
this code works properly in python 3.5, but does not in 3.7 due to the change introduced
in the mentioned &lt;a href=&quot;https://www.python.org/dev/peps/pep-0479/&quot;&gt;PEP479&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Simply changing:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Flag generator is exhausted
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;StopIteration&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;with&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Flag generator is exhausted
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;solved the issue.&lt;/p&gt;

&lt;h2 id=&quot;lesson-3-check-silent-deprecation-warnings&quot;&gt;Lesson 3: Check silent deprecation warnings&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://www.python.org/dev/peps/pep-0479/#transition-plan&quot;&gt;PEP-479&lt;/a&gt; describes very clearly
the transition plan in regards to the backwards incompatible change:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Python 3.5: Enable new semantics under &lt;strong&gt;future&lt;/strong&gt; import; silent deprecation warning if StopIteration bubbles out of a generator not under &lt;strong&gt;future&lt;/strong&gt; import.&lt;/li&gt;
  &lt;li&gt;Python 3.6: Non-silent deprecation warning.&lt;/li&gt;
  &lt;li&gt;Python 3.7: Enable new semantics everywhere.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As I upgraded from 3.5 to 3.7, I didn’t get any deprecation warning. Configuring &lt;a href=&quot;https://docs.python.org/3.5/library/warnings.html&quot;&gt;PYTHONWARNINGS&lt;/a&gt; environment variable is a straight forward
way to get this kind of warnings.&lt;/p&gt;

&lt;h2 id=&quot;lesson-4-bring-future-default-behaviour-to-your-code&quot;&gt;Lesson 4: Bring future default behaviour to your code&lt;/h2&gt;

&lt;p&gt;I took this opportunity to review what exactly &lt;a href=&quot;https://docs.python.org/3.5/reference/simple_stmts.html#future-statements&quot;&gt;&lt;strong&gt;__future__ statements&lt;/strong&gt;&lt;/a&gt; tackles.&lt;/p&gt;

&lt;p&gt;In regards to StopIteration breaking change, Python 3.5 introduced the chance to write
your code in the way that is required in 3.7 (check the first point in the transition
plan above). It’s really convenient to be ready for your next interpreter/library
upgrade. In this specific case, all I needed to do was adding the following
line on top of the gdrive API wrapper:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;__future__&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;generator_stop&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;That way, running the code in a python 3.5 will behave as python 3.7, hence raising an error
unless &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StopIteration&lt;/code&gt; is changed by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;return&lt;/code&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Kubernetes persistent volumes on top of AWS EFS</title>
   <link href="http://juandebravo.com/2018/09/28/aws-efs-kubernetes/"/>
   <updated>2018-09-28T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2018/09/28/aws-efs-kubernetes/</id>
   <content type="html">&lt;p&gt;When deploying an application in a containers based environment, one of the usual
challenges to tackle is how/where to store application state if your application happens to
require it, which is usually the case.&lt;/p&gt;

&lt;p&gt;Today I was tackling one of the recurrent issues while building a web application: an user should
be able to upload a file (an image in this case) and retrieve it later. This obviously means
storing the file in the server side.&lt;/p&gt;

&lt;p&gt;Files inside a container are ephemeral, there’s no guarantee how long a container will be alive,
and therefore local state inside the container is not an option (it’s usually not an option if
you want to scale horizontally).&lt;/p&gt;

&lt;p&gt;In this scenario, the state is represented by a binary file. While there’re multiples solutions
for this use case, using a shared disk that can be mounted by a set of nodes is what I’m more used to.&lt;/p&gt;

&lt;p&gt;But working with kubernetes, &lt;em&gt;“mounting a shared disk in a set of nodes”&lt;/em&gt; is not that straight forward.&lt;/p&gt;

&lt;p&gt;In this post I’ll go through the relevant kubernetes resources for tackling this problem, and specifically
how to implement it on top of &lt;a href=&quot;https://aws.amazon.com/&quot;&gt;AWS&lt;/a&gt; using an &lt;a href=&quot;https://aws.amazon.com/efs/&quot;&gt;EFS&lt;/a&gt;
storage resource.&lt;/p&gt;

&lt;h1 id=&quot;the-basic-a-kubernetes-volume&quot;&gt;The basic. A kubernetes Volume&lt;/h1&gt;

&lt;p&gt;A &lt;a href=&quot;https://kubernetes.io/docs/concepts/storage/volumes/&quot;&gt;&lt;strong&gt;Volume&lt;/strong&gt;&lt;/a&gt; is a kubernetes storage resource &lt;strong&gt;attached
to a Pod&lt;/strong&gt;, and it lives as long as the Pod it’s attached to does.&lt;/p&gt;

&lt;p&gt;Those are the usual scenarios where I’ve been using a Volume so far:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;mount &lt;a href=&quot;https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/&quot;&gt;ConfigMap&lt;/a&gt; data
using a &lt;a href=&quot;https://kubernetes.io/docs/concepts/storage/volumes/#configmap&quot;&gt;configMap&lt;/a&gt; Volume type. This is handy
for creating files in the container with the ConfigMap information.&lt;/li&gt;
  &lt;li&gt;share state between containers that are part of the same Pod using an
&lt;a href=&quot;https://kubernetes.io/docs/concepts/storage/volumes/#emptydir&quot;&gt;emptyDir&lt;/a&gt; Volume type.&lt;/li&gt;
  &lt;li&gt;mount an external block storage, like &lt;a href=&quot;https://aws.amazon.com/ebs/&quot;&gt;Amazon EBS&lt;/a&gt;
or &lt;a href=&quot;https://cloud.google.com/compute/docs/disks/&quot;&gt;Google Persistent Disk&lt;/a&gt;, using
&lt;a href=&quot;https://kubernetes.io/docs/concepts/storage/volumes/#awselasticblockstore&quot;&gt;awsElasticBlockStore&lt;/a&gt;
and &lt;a href=&quot;https://kubernetes.io/docs/concepts/storage/volumes/#gcepersistentdisk&quot;&gt;gcePersistentDisk&lt;/a&gt; respectively. This
is useful if you need to store data which availability is limited to one container at a time (no need to share
state between pods), so data will nb. Note that the external resources must be created before you can use them in kubernetes via the
cloud provider Web console or command line tool.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While the Volume is indeed convenient for the scenarios described above, there’s a big limitation:
it can be mounted only in one Pod. Therefore, a Volume is not a good solution for my scenario, where I
need binary files to be available in several Pods (to scale horizontally the solution).&lt;/p&gt;

&lt;h1 id=&quot;the-advanced-a-kubernetes-persistent-volume&quot;&gt;The advanced. A kubernetes Persistent Volume&lt;/h1&gt;

&lt;p&gt;A &lt;a href=&quot;https://kubernetes.io/docs/concepts/storage/persistent-volumes/&quot;&gt;&lt;strong&gt;Persistent Volume&lt;/strong&gt;&lt;/a&gt; is a cluster
resource on its own and has its own lifecycle. It represents a storage resource available to any Pod created in the cluster.
Not being attached to a specific node/pod is one of the main differences with a &lt;strong&gt;Volume&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Similar to how &lt;a href=&quot;https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/&quot;&gt;memory and CPU resources&lt;/a&gt;
can be configured in a Pod specification, a Pod storage requirements (Persistent Volume) can be defined using a &lt;a href=&quot;https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims&quot;&gt;&lt;strong&gt;PersistentVolumeClaim&lt;/strong&gt;&lt;/a&gt;
definition. There’re two attributes that can be configured: &lt;em&gt;size&lt;/em&gt; and &lt;em&gt;access mode&lt;/em&gt; (read, write).&lt;/p&gt;

&lt;p&gt;Mind the difference between these two concepts: a &lt;em&gt;Persistent Volume&lt;/em&gt; is a cluster resource (like nodes, memory, CPU),
while and a &lt;em&gt;Persistent Volume Claim&lt;/em&gt; is a set of requirements about the storage a Pod needs.&lt;/p&gt;

&lt;p&gt;Last but not least concept is the &lt;a href=&quot;https://kubernetes.io/docs/concepts/storage/storage-classes/&quot;&gt;&lt;strong&gt;StorageClass&lt;/strong&gt;&lt;/a&gt; kind,
which is used to describe a storage resource (similar to include metadata or define several profiles).
A pod storage requirements can be configured either by defining size and access mode via &lt;em&gt;PVC&lt;/em&gt;, or by defining the
needs in more abstract terms, using a &lt;em&gt;StorageClass&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A Persistent Volume can be &lt;a href=&quot;https://kubernetes.io/docs/concepts/storage/persistent-volumes/#provisioning&quot;&gt;provisioned
dynamically&lt;/a&gt; by means of a StorageClass
definition (using the parameter &lt;em&gt;provisioner&lt;/em&gt;).&lt;/p&gt;

&lt;h1 id=&quot;steps-to-mount-an-efs-resource-in-a-pod&quot;&gt;Steps to mount an EFS resource in a Pod&lt;/h1&gt;

&lt;p&gt;Back to my original problem, how can I mount a disk for sharing state (binary files) between Pods?&lt;/p&gt;

&lt;p&gt;Running a kubernetes cluster in AWS, it seems like &lt;a href=&quot;https://aws.amazon.com/efs/&quot;&gt;EFS&lt;/a&gt; is the natural choice.&lt;/p&gt;

&lt;p&gt;Those are the steps I went through:&lt;/p&gt;

&lt;h4 id=&quot;1-create-an-efs-resource-and-make-it-available-to-kubernetes-nodes-using-aws-cli&quot;&gt;1. Create an EFS resource and make it available to kubernetes nodes using aws cli&lt;/h4&gt;

&lt;p&gt;An &lt;strong&gt;EFS resource&lt;/strong&gt; can be created executing the following command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;aws efs create-file-system --creation-token efs-for-testing
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The response is a JSON payload including a field named &lt;em&gt;FileSystemId&lt;/em&gt;, which represents the unique identifier
that should be used to manage the EFS volume. Let’s assume the &lt;em&gt;FileSystemId&lt;/em&gt; is &lt;em&gt;fs-testing&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;EFS creation is an asynchronous process, and before managing it you need to make sure its LifeCycleState is
&lt;em&gt;available&lt;/em&gt;. The EFS state can be checked as follows:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;aws efs describe-file-systems --file-system-id fs-testing
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once the EFS is available,  next step is creating a &lt;strong&gt;mount target&lt;/strong&gt; associated to it. A mount target acts as a
virtual firewall, defining a subnet and a security group that is granted permissions to mount the EFS volume.&lt;/p&gt;

&lt;p&gt;For creating the mount target you need the &lt;em&gt;subnet-id&lt;/em&gt; and &lt;em&gt;security-groups&lt;/em&gt; associated to your kubernetes cluster nodes.
Usual scenario is that every node will share the same security group, while subnet id will differ based on the Availability
Zone where the node is located:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;aws ec2 describe-instances --filters &amp;amp;lt;your-filters-to-retrieve-k8s-nodes&amp;amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Per each SubnetId and SecurityGroupId execute the following command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;aws efs create-mount-target \
--file-system-id fs-testing \
--subnet-id {SubnetId} \
--security-groups {SecurityGroupId}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;2-deploy-the-efs-provisioner&quot;&gt;2. Deploy the EFS provisioner&lt;/h4&gt;

&lt;p&gt;A Kubernetes deployment includes, by default, several
&lt;a href=&quot;https://kubernetes.io/docs/concepts/storage/persistent-volumes/#types-of-persistent-volumes&quot;&gt;Persistent Volume types&lt;/a&gt;, like
AWSElasticBlockStore, GCEPersistentDisk, AzuleFile and NFS for naming a few. Each of them defines a
&lt;a href=&quot;https://github.com/kubernetes/kubernetes/tree/a8e8e891f29e83362636dfdbed3e8cf768ba1862/pkg/volume&quot;&gt;specific provisioner&lt;/a&gt;
that can be used to create a PV.&lt;/p&gt;

&lt;p&gt;Furthermore, the kubernetes incubator &lt;a href=&quot;https://github.com/kubernetes-incubator/external-storage&quot;&gt;&lt;strong&gt;external-storage repository&lt;/strong&gt;&lt;/a&gt;
holds additional Persistent Volumes that are not part of a Kubernetes default deployment, and here I found the
answer to my specific need: the
&lt;a href=&quot;https://github.com/kubernetes-incubator/external-storage/tree/master/aws/efs&quot;&gt;&lt;strong&gt;EFS provisioner&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The EFS provisioner is a &lt;a href=&quot;https://kubernetes.io/docs/concepts/workloads/controllers/deployment/&quot;&gt;deployment&lt;/a&gt; that runs
a container with access to the AWS EFS resource. It acts as an EFS broker, allowing other pods to mount the EFS
resource as a PV.&lt;/p&gt;

&lt;p&gt;These are the definitions I used for deploying the EFS provisioner, even though you can find a
very similar definitions in &lt;a href=&quot;https://github.com/kubernetes-incubator/external-storage/tree/master/aws/efs/deploy&quot;&gt;kubernetes-incubator github
repository&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ConfigMap&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;efs-provisioner&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;file.system.id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;lt;&amp;lt;your-efs-id&amp;gt;&amp;gt;&apos;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;aws.region&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;lt;&amp;lt;your-region-id&amp;gt;&amp;gt;&apos;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;provisioner.name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mycompany.com/aws-efs&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Deployment&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;extensions/v1beta1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;efs-provisioner&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;replicas&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;strategy&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Recreate&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;efs-provisioner&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;containers&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;efs-provisioner&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;quay.io/external_storage/efs-provisioner:latest&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;FILE_SYSTEM_ID&lt;/span&gt;
              &lt;span class=&quot;na&quot;&gt;valueFrom&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;configMapKeyRef&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
                  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;efs-provisioner&lt;/span&gt;
                  &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;file.system.id&lt;/span&gt;
            &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;AWS_REGION&lt;/span&gt;
              &lt;span class=&quot;na&quot;&gt;valueFrom&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;configMapKeyRef&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
                  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;efs-provisioner&lt;/span&gt;
                  &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;aws.region&lt;/span&gt;
            &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;PROVISIONER_NAME&lt;/span&gt;
              &lt;span class=&quot;na&quot;&gt;valueFrom&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;configMapKeyRef&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
                  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;efs-provisioner&lt;/span&gt;
                  &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;provisioner.name&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;volumeMounts&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;pv-volume&lt;/span&gt;
              &lt;span class=&quot;na&quot;&gt;mountPath&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/persistentvolumes&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;pv-volume&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;nfs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;lt;&amp;lt;your-efs-id&amp;gt;&amp;gt;.efs.&amp;lt;&amp;lt;your-region-id&amp;gt;&amp;gt;.amazonaws.com&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;kubectl apply -f efs-provisioner.yaml&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;3-define-the-storageclass-kind&quot;&gt;3. Define the StorageClass kind&lt;/h4&gt;

&lt;p&gt;StorageClass is used as an intermediate step for connecting a &lt;em&gt;PersistentVolumeClaim&lt;/em&gt; with a specific storage resource:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;metadata.name&lt;/em&gt; field is used to refer to the resource.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;provisioner&lt;/em&gt; is used to identify the provisioner (EFS provisioner in this case).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: An StorageClass definition cannot be updated.&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;StorageClass&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;storage.k8s.io/v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;aws-efs&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;provisioner&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mycompany.com/aws-efs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;kubectl apply -f storage-class.yaml&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;4-define-the-persistentvolumeclaim&quot;&gt;4. Define the PersistentVolumeClaim&lt;/h4&gt;

&lt;p&gt;The &lt;strong&gt;PVC&lt;/strong&gt; definition connects access mode and size requirements with a specific StorageClass item.
In this case, as EFS has unlimited storage, the size requested won’t have any real impact.&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;PersistentVolumeClaim&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;v1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;efs&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;storageClassName&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;aws-efs&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;accessModes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ReadWriteMany&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;requests&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;storage&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;1Gi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;kubectl apply -f pvc.yaml&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As soon as you create the PVC, the EFS provisioner will get notified and will create a PV that matches the requirements.
These are the EFS provisioner logs showing the PV creation:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;I0928 11:03:45.897983       1 controller.go:987] provision &quot;default/efs&quot; class &quot;aws-efs&quot;: started
I0928 11:03:45.900711       1 event.go:221] Event(v1.ObjectReference{Kind:&quot;PersistentVolumeClaim&quot;, Namespace:&quot;default&quot;, Name:&quot;efs&quot;, UID:&quot;2b56b224-c30e-11e8-abf5-023d3cfc37fe&quot;, APIVersion:&quot;v1&quot;, ResourceVersion:&quot;52345195&quot;, FieldPath:&quot;&quot;}): type: &apos;Normal&apos; reason: &apos;Provisioning&apos; External provisioner is provisioning volume for claim &quot;default/efs&quot;
I0928 11:03:45.950090       1 controller.go:1087] provision &quot;default/efs&quot; class &quot;aws-efs&quot;: volume &quot;pvc-2b56b224-c30e-11e8-abf5-023d3cfc37fe&quot; provisioned
I0928 11:03:45.950116       1 controller.go:1101] provision &quot;default/efs&quot; class &quot;aws-efs&quot;: trying to save persistentvvolume &quot;pvc-2b56b224-c30e-11e8-abf5-023d3cfc37fe&quot;
I0928 11:03:45.956467       1 controller.go:1108] provision &quot;default/efs&quot; class &quot;aws-efs&quot;: persistentvolume &quot;pvc-2b56b224-c30e-11e8-abf5-023d3cfc37fe&quot; saved
I0928 11:03:45.956498       1 controller.go:1149] provision &quot;default/efs&quot; class &quot;aws-efs&quot;: succeeded
I0928 11:03:45.956643       1 event.go:221] Event(v1.ObjectReference{Kind:&quot;PersistentVolumeClaim&quot;, Namespace:&quot;default&quot;, Name:&quot;efs&quot;, UID:&quot;2b56b224-c30e-11e8-abf5-023d3cfc37fe&quot;, APIVersion:&quot;v1&quot;, ResourceVersion:&quot;52345195&quot;, FieldPath:&quot;&quot;}): type: &apos;Normal&apos; reason: &apos;ProvisioningSucceeded&apos; Successfully provisioned volume pvc-2b56b224-c30e-11e8-abf5-023d3cfc37fe
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And now you can retrieve both PV and PVC using &lt;em&gt;kubectl&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl get pv
NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS    CLAIM         STORAGECLASS   REASON    AGE
persistentvolume/pvc-2b56b224-c30e-11e8-abf5-023d3cfc37fe   1Gi        RWX            Delete           Bound     default/efs       aws-efs              4m

kubectl get pvc
NAME                        STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/efs   Bound     pvc-2b56b224-c30e-11e8-abf5-023d3cfc37fe   1Gi        RWX            aws-efs        4m
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;5-create-a-deployment-with-2-replicas-and-mount-the-volume&quot;&gt;5. Create a Deployment with 2 replicas and mount the Volume&lt;/h4&gt;

&lt;p&gt;Pods get access to the PV storage by defining the claim as a volume in the Pod definition.
Claims must exist in the same namespace as the pods using the claim (StorageClass and
PersistentVolume are global kinds in the cluster).&lt;/p&gt;

&lt;p&gt;The snippet below is a basic Deployment example with 2 pods mouting a volume using a PVC.
Each Pod will generate a single file in the shared folder and check that the folder has additional files, which
would reflect that indeed the other Pod has created its file.&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;apps/v1beta1&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Deployment&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;test-efs&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;replicas&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;strategy&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Recreate&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;test-efs&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;restartPolicy&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Always&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;containers&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;test-pod&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;gcr.io/google_containers/busybox:1.24&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;sh&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-c&apos;&lt;/span&gt;
          &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;touch&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;${MEDIA_PATH}/${MY_POD_NAME}&quot;;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;echo&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;File&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;created,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;waiting&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;bit&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ensure&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;the&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;had&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;the&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;well&quot;;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;5;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;$(ls&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-l&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;$MEDIA_PATH&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;wc&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-l)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-gt&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;(echo&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Both&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;pods&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;generated&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;the&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;file!&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;0)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;||&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;(echo&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Unable&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;both&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;the&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;shared&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;folder&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;1)&apos;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;MY_POD_NAME&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;valueFrom&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
              &lt;span class=&quot;na&quot;&gt;fieldRef&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;fieldPath&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;metadata.name&lt;/span&gt;
          &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;MEDIA_PATH&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/var/media/uploads&quot;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;volumeMounts&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;efs-pvc&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;mountPath&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/var/media/uploads&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;efs-pvc&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;persistentVolumeClaim&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;claimName&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;efs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Checking the Pods logs we can see that the scenario is successfully validated:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubetail --selector app=test-efs
Will tail 2 logs...
test-efs-546d6d7456-2fvgp
test-efs-546d6d7456-2gqx6
[test-efs-546d6d7456-2fvgp] File created, waiting a bit to ensure the other Pod had the time as well
[test-efs-546d6d7456-2gqx6] File created, waiting a bit to ensure the other Pod had the time as well
[test-efs-546d6d7456-2fvgp] Both pods generated the file!
[test-efs-546d6d7456-2gqx6] Both pods generated the file!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h1&gt;

&lt;p&gt;While not very obvious, once you interiorize the concepts around persistent storage, having a shared folder mounted
in several Pods in a kubernetes cluster running in AWS is quite straight forward.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Impact of Amazon Prime in my purchase habits</title>
   <link href="http://juandebravo.com/2018/09/09/impact-of-having-amazon-prime/"/>
   <updated>2018-09-09T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2018/09/09/impact-of-having-amazon-prime/</id>
   <content type="html">&lt;p&gt;Summertime is always a great opportunity for me to read more frequently than usual.
This August I’ve read two interesting books related to data analysis in python:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://jakevdp.github.io/PythonDataScienceHandbook/&quot;&gt;Python Data Science Handbook&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.apress.com/de/book/9781484238011&quot;&gt;Personal Finance with Python: using pandas, Requests and Recurrent&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In &lt;a href=&quot;https://www.apress.com/de/book/9781484238011&quot;&gt;Personal Finance with Python: using pandas, Requests and Recurrent&lt;/a&gt; last chapter,
the author talked about times series forecasting and how he used
&lt;a href=&quot;https://research.fb.com/prophet-forecasting-at-scale/&quot;&gt;Prophet&lt;/a&gt; to estimate his future
expenses in Amazon.&lt;/p&gt;

&lt;p&gt;The book referenced a CSV file including the author’s Amazon purchases since 2012, hence I
guessed there might be a simple way to download a CSV report from Amazon including
every purchase the logged in user did in the website.
As I’ll explain in the following paragraphs I was wrong and it wasn’t that easy,
but in any case that chapter gave me a hint to explore something I was
curious about: &lt;strong&gt;What was the impact of becoming an Amazon Prime customer in my
Amazon purchases habits?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No matter if you’re working with big or little data, the major steps you need to follow
for data analysis can be summarized as follows (if you’re a data analyst and don’t agree
with these steps, you’re probably right!):&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Data gathering&lt;/strong&gt;: this step focuses on obtaining the data from one (in case you’re lucky)
or more (the real world) sources.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Data normalization&lt;/strong&gt;: in case you have more than one source of data or data structure,
a normalization phase is required (or at least recommended!).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Data munging&lt;/strong&gt;: “The difference between data found in many tutorials
and data in the real world is that real-world data is rarely clean and homogeneous”. Great
sentence by Jake VanderPlas in &lt;a href=&quot;https://jakevdp.github.io/PythonDataScienceHandbook/&quot;&gt;Python Data Science Handbook&lt;/a&gt;. He is right :-)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Data analysis and plot&lt;/strong&gt;: execute the right algorithm and plot the data in a graph that
will help you to understand the meaning of the data (extract information out of the data).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In order to analyse the impact of Amazon Prime, I went through these four steps, which I’ll
describe in the following paragraphs.&lt;/p&gt;

&lt;h2 id=&quot;data-gathering&quot;&gt;Data gathering&lt;/h2&gt;

&lt;p&gt;I googled “Amazon purchases CSV report” and apparently &lt;em&gt;https://www.amazon.es/gp/b2b/reports&lt;/em&gt;
was the place I was looking for (mind the &lt;em&gt;.es&lt;/em&gt; domain).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/amazon-prime/amazon-csv-spain.png&quot; alt=&quot;Amazon Spain CSV report&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Well… a web form not using a single language is not what you’d expect from a
&lt;a href=&quot;https://money.cnn.com/2018/09/04/technology/amazon-1-trillion/index.html&quot;&gt;trillion dollar valuation company&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I filled in the form to download the data and… uppss!! It didn’t work. So I went to the
amazon.com site (instead of amazon.es), as I assumed there was a temporal issue in the
Spain web portal.
In amazon.com things indeed got better, now I had a web form with a single language (English) and
I was able to download my CSV report.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/amazon-prime/amazon-csv-us.png&quot; alt=&quot;Amazon US CSV report&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Wait!! The report included data only from 2011 to 2012. I was certainly sure I had purchased
more stuff in Amazon in the following years, so something was wrong there.&lt;/p&gt;

&lt;p&gt;Suddendly I realized it was some years ago when Amazon launched amazon.es website, and since
then I was not able to buy anymore in amazon.com (at least if the same stuff was available
in amazon.es). Apparently single sign on works like a charm between amazon.com and amazon.es,
but each data report is available only in the website where the purchase was done,
and after 2012 all my purchases had happened in amazon.es. Building global products is hard!!&lt;/p&gt;

&lt;p&gt;I was able to review in Amazon Spain website the purchases I did since 2012, but as mentioned
at the beginning I was not able to download an automatically generated report.&lt;/p&gt;

&lt;p&gt;I decided to generate the CSV report manually. I’m not a really big Amazon customer so
eventually it didn’t take me more than one hour to generate it.&lt;/p&gt;

&lt;p&gt;Now I was ready for the first interesting step.&lt;/p&gt;

&lt;h2 id=&quot;data-normalization&quot;&gt;Data normalization&lt;/h2&gt;

&lt;p&gt;Cool, so now I had two files, &lt;em&gt;juan-amazon-us.csv&lt;/em&gt; and &lt;em&gt;juan-amazon-es.csv&lt;/em&gt;, each of them holding
a report with my purchases in a single Amazon online store.&lt;/p&gt;

&lt;p&gt;Next step was data normalization. I was specifically interested in:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;filter out fields from the CSV&lt;/em&gt; that I considered private data, so I could upload to
the wild Internet the CSV report (in case someone is interested in playing with the &lt;a href=&quot;https://github.com/juandebravo/amazon-prime-analysis/blob/master/notebook.ipynb&quot;&gt;Jupyter
notebook&lt;/a&gt;).&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;currency normalization&lt;/em&gt;: US items were purchased in dollars, while ES items were in euros. I
decided to convert euros to dollars.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;merge both files&lt;/em&gt;: generate a single source for loading and analysing the data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While python and a library like &lt;a href=&quot;https://pandas.pydata.org/&quot;&gt;pandas&lt;/a&gt; might be a good fit
for tackling the topics above, I preferred to implement this step directly as an script on top of bash.
I have spent a considerable amount of time during my last year in the bash console,
so I felt pretty confident about it.
I did a couple of tests with the usual bash commands (cat, cut, awk, …) but eventually
I decided to give a try to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jqlite&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://gist.github.com/drslump/cdacaa368a1d63bab717efd3414b4467&quot;&gt;&lt;strong&gt;jqlite&lt;/strong&gt;&lt;/a&gt; is a wrapper on top of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sqlite&lt;/code&gt; implemented by my colleague
&lt;a href=&quot;https://github.com/drslump&quot;&gt;@drslump&lt;/a&gt;, which provides a SQL interface on top of
tabular data (CSV, TSV, JSON).&lt;/p&gt;

&lt;p&gt;It looked like a perfect match for the scenario I was interested in:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;SELECT&lt;/em&gt; for fetching those fields I was ok to expose, and filtering out those I was not.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;CASE…END&lt;/em&gt; for currency conversion.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;UNION ALL&lt;/em&gt; for merging both files.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I came up with the following query:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;SELECT date
      , orderId
      , CASE WHEN currency = &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;€&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; THEN amount*1.1 ELSE amount END as amount
     FROM (
         SELECT &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Order Date&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; as date,
                &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Order ID&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; as orderId,
                substr(&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Item Total&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, 2) as amount,
                substr(&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Item Total&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, 1,1) as currency
         FROM (
            SELECT * FROM SPAIN UNION ALL SELECT * FROM USA
         )
     )&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
| jqlite &lt;span class=&quot;s2&quot;&gt;&quot;data/juan-amazon-es.csv@SPAIN&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;data/juan-amazon-us.csv@USA&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;At this point, my data was filtered, normalized and combined in &lt;a href=&quot;https://github.com/juandebravo/amazon-prime-analysis/blob/master/data/juan-amazon.csv&quot;&gt;a
single file&lt;/a&gt;,
ready to move to the python and pandas world.&lt;/p&gt;

&lt;h2 id=&quot;data-munging&quot;&gt;Data munging&lt;/h2&gt;

&lt;p&gt;With unnecessary fields dropped out and data normalisation done in the previous step,
now it was time to model the data to be able to plot it with ease.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://pandas.pydata.org/&quot;&gt;Pandas&lt;/a&gt; is a really convenient library for working
with time series, and I really enjoyed learning about it with
&lt;a href=&quot;https://www.safaribooksonline.com/library/view/python-data-science&quot;&gt;Python Data Science Handbook&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The steps I followed to model the data were:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Load the CSV into memory and create a Panda DataFrame with the columns (date,orderId,amount).&lt;/li&gt;
  &lt;li&gt;Reduce purchase time granularity from day to month.&lt;/li&gt;
  &lt;li&gt;Set the month column as Pandas DataFrame index.&lt;/li&gt;
  &lt;li&gt;Generate a Pandas Series having as index a time series from the minimum month when I made a purchase till now, and zeros as value.&lt;/li&gt;
  &lt;li&gt;Calculate the number of purchases and total amount per month.&lt;/li&gt;
  &lt;li&gt;Calculate the accumulated spent in every month.&lt;/li&gt;
  &lt;li&gt;Fill NaN values with the relevant data.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can find the actual code in the github repository that contains the
&lt;a href=&quot;https://github.com/juandebravo/amazon-prime-analysis&quot;&gt;Jupyter notebook&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;data-analysis-and-plot&quot;&gt;Data analysis and plot&lt;/h2&gt;

&lt;p&gt;I became an Amazon prime customer in June 2017. In the following graphs you can see:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the total amount spent from 2011 till 2018.&lt;/li&gt;
  &lt;li&gt;the number of orders, per month.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vertical line shows the exact moment when I became an Amazon Prime user.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/amazon-prime/amazon-purchases.png&quot; alt=&quot;Amazon Puchases analysis&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h2&gt;

&lt;p&gt;Even though the total amount spent grew considerable after me becoming an Amazon Prime customer,
I think the most relevant conclusion is that after that date (June 2017) I’ve purchased in Amazon
at least one item at almost every month.&lt;/p&gt;

&lt;p&gt;So even though Amazon Prime price in Spain &lt;del&gt;is&lt;/del&gt;
(&lt;a href=&quot;https://www.businessinsider.es/precio-amazon-prime-espana-dispara-80-partir-ahora-costara-36-euros-ano-296745&quot;&gt;was&lt;/a&gt;) cheap, it seems like a big win for Amazon to subsidize it.&lt;/p&gt;

&lt;p&gt;Last, but not least, I’ll put some effort in reducing the amount of purchases I do in Amazon in favor
of local shops.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Smudge and clean your git working directory</title>
   <link href="http://juandebravo.com/2017/12/02/git-filter-smudge-and-clean/"/>
   <updated>2017-12-02T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2017/12/02/git-filter-smudge-and-clean/</id>
   <content type="html">&lt;p&gt;Some years ago I learned about &lt;strong&gt;smudging and cleaning data in a git repository&lt;/strong&gt;,
a very cool git functionality that I haven’t used for a while till last week,
when it came back to my mind for solving a specific need.&lt;/p&gt;

&lt;p&gt;Smudge and clean are two functionalities that can be configured via &lt;a href=&quot;https://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes&quot;&gt;git
attributes&lt;/a&gt;.
While git attributes are not a very popular git configuration, it provides
several handy functionalities:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;identify files as binary files&lt;/strong&gt;: this can be convenient to skip those files in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git show&lt;/code&gt;
and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git diff&lt;/code&gt; output (by default, git does not know how to compare binary files).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;configure a tool/script for &lt;strong&gt;diffing binary files&lt;/strong&gt;: relevant in case you don’t want to
skip binary files while checking changes in your working directory but instead
be able to show a meaningful diff information. e.g. In case you want to compare
two versions of a video binary file, you could use
&lt;a href=&quot;https://www.sno.phy.queensu.ca/~phil/exiftool/&quot;&gt;exiftool&lt;/a&gt; to obtain metadata information
from the two versions and compare it.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;define merge strategies for specific files/paths.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;configure your preferences for archiving your repository.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;update files automatically upon checkout/commit: it’s possible to change automatically
the file content right after running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git checkout&lt;/code&gt; or right before running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit&lt;/code&gt;.
This is the functionality I will focus on.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;smudging-your-checkout&quot;&gt;Smudging your checkout&lt;/h3&gt;

&lt;p&gt;Let’s say you need a secret token in your code inside the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;config.h&lt;/code&gt; file, you want to
commit that file to the git repository, but you don’t want it to contain sensible
information.&lt;/p&gt;

&lt;p&gt;Simplest solution would be to create a placeholder (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{your-secret-token}&lt;/code&gt;)
that should be updated with the right value (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;super-secret-value!&lt;/code&gt;) upon checkout:&lt;/p&gt;

&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secretToken&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;{your-secret-token}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;# After checkout, the line should be updated to:
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secretToken&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;super-secret-value!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As soon as you update the file to include your secret value, the file will be shown
as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;modified&lt;/code&gt; in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git status&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;Thanks to the smudge filter, you can:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;automate the process, so &lt;strong&gt;the file will be updated automatically upon checkout&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;prevent the file change to be part of the git diff output.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You need two steps for configuring a smudge filter:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Identify in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitattributes&lt;/code&gt; file the files that should be processed by the filter.
In this simple example we want to process the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;config.h&lt;/code&gt; file using a filter
named &lt;em&gt;updateSecretToken&lt;/em&gt;:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# .gitattributes file
config.h filter=updateSecretToken
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;Define the smudge filter &lt;em&gt;updateSecretToken&lt;/em&gt;, that will substitute the placeholder
with your secret. This can be done in the git global configuration:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; filter.updateSecretToken.smudge &lt;span class=&quot;s1&quot;&gt;&apos;sed &quot;s/{your-secret-token}/super-secret-value!/&quot;&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Next time you checkout the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;config.h&lt;/code&gt; file, its content will be automatically updated and
your secret will be included in the file.&lt;/p&gt;

&lt;h3 id=&quot;cleaning-your-commit&quot;&gt;Cleaning your commit&lt;/h3&gt;

&lt;p&gt;As much as you need to update the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;config.h&lt;/code&gt; file content upon checkout to include your
secret, it’s important as well to update the content before including the file
in the stage area, and put back &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{your-secret-token}&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;super-secret-value!&lt;/code&gt;. Otherwise,
your secret would be exposed.&lt;/p&gt;

&lt;p&gt;For doing it, you can define the clean filter &lt;em&gt;updateSecretToken&lt;/em&gt;. Similar to
the smudge filter, this can be done in the git global config:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; filter.updateSecretToken.clean &lt;span class=&quot;s1&quot;&gt;&apos;sed &quot;s/super-secret-value!/{your-secret-token}/&quot;&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/gfx/posts/smudge-and-clean/smudge-clean-git-filters.png&quot; alt=&quot;Smudge and clean filters&quot; /&gt;&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>WebRTC. Improve the setup time with Chrome 59</title>
   <link href="http://juandebravo.com/2017/04/01/improve-setup-time-webrtc/"/>
   <updated>2017-04-01T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2017/04/01/improve-setup-time-webrtc/</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://webrtc.org/architecture/&quot;&gt;WebRTC architecture&lt;/a&gt; relies on
&lt;a href=&quot;https://tools.ietf.org/html/rfc5245&quot;&gt;ICE protocol&lt;/a&gt; for checking
connectivity between peers and choosing the best interface for them to communicate.
The basic idea behind ICE is that each peer in the communication has a variety of
candidate transport addresses (combination of IP address and port for
a particular transport protocol) it could use to communicate with the other peer.
ICE helps on gathering the candidate transport addresses, check connectivities
and choose the best path for the communication. &lt;strong&gt;Gathering candidates require
a time that can be critical to reduce as much as possible to provide a good
user experience&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Last week my colleague &lt;a href=&quot;https://twitter.com/anarchyco&quot;&gt;Gustavo&lt;/a&gt; reviewed
some slides I was preparing for &lt;a href=&quot;http://www.juandebravo.com/webrtc-demo-tid/&quot;&gt;a lecture about WebRTC
in Telefonica R&amp;amp;D&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In one slide, I mentioned that &lt;em&gt;setLocalDescription&lt;/em&gt; API indirectly controls
the candidate gathering process. Gustavo raised that the ICE candidates
gathering can start before calling &lt;em&gt;setLocalDescription&lt;/em&gt;, as it’s defined
in the &lt;a href=&quot;https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-19#section-3.5.4&quot;&gt;JSEP protocol&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;JSEP applications typically inform the JSEP implementation to begin
   ICE gathering via the information supplied to setLocalDescription, as
   this is where the app specifies the number of media streams, and
   thereby ICE components, for which to gather candidates.  However, to
   accelerate cases where the application knows the number of ICE
   components to use ahead of time, it may ask the implementation to
   gather a pool of potential ICE candidates to help ensure rapid media
   setup.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While Gustavo was right and the specification indeed mentioned that possibility,
in my tests I never was able to have such behaviour, as the candidates gathering
happened only after calling the &lt;em&gt;setLocalDescription&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;But there are good news for the near future :relaxed: : &lt;a href=&quot;https://bugs.chromium.org/p/chromium/issues/detail?id=673395&quot;&gt;Chrome 59&lt;/a&gt;
implements the &lt;a href=&quot;https://www.w3.org/TR/webrtc/#dom-rtcconfiguration-icecandidatepoolsize&quot;&gt;iceCandidatePoolSize member of
RTCConfiguration&lt;/a&gt;,
that instructs the RTCPeerConnection instance to gather, as a performance
optimization, ICE candidates before calling &lt;em&gt;setLocalDescription&lt;/em&gt;. No news
about when &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1291894&quot;&gt;Firefox will implement this functionality&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In a simple demo that you can find &lt;a href=&quot;https://jsfiddle.net/rn22efjd/4/&quot;&gt;here&lt;/a&gt;, the
time required for getting the user media, creating the peer connection and completing
the candidates gathering is reduced from 221ms to 180ms, around 19% reduction.&lt;/p&gt;

&lt;p&gt;Reducing as much as possible the call setup time is a key factor
for providing a good user experience, and being able to start the connectivity checks
before creating the offer will indeed help on that.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>WebRTC. Chrome 57 to set multiplexing policy to require by default</title>
   <link href="http://juandebravo.com/2017/02/15/rtcp-mux-in-webrtc/"/>
   <updated>2017-02-15T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2017/02/15/rtcp-mux-in-webrtc/</id>
   <content type="html">&lt;p&gt;Real-time Transport Protocol (&lt;a href=&quot;https://tools.ietf.org/html/rfc3550&quot;&gt;RTP&lt;/a&gt;)
includes two separate components:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the data transfer protocol itself (&lt;strong&gt;RTP&lt;/strong&gt;).&lt;/li&gt;
  &lt;li&gt;a control protocol associated to the data (&lt;strong&gt;RTCP&lt;/strong&gt;, where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C&lt;/code&gt; stands for &lt;em&gt;Control&lt;/em&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The RTP protocol &lt;a href=&quot;https://tools.ietf.org/html/rfc3550&quot;&gt;specification&lt;/a&gt; states that
the “&lt;em&gt;underlying protocol MUST provide multiplexing of the data and control packets,
for example using separate port numbers with UDP&lt;/em&gt;”.&lt;/p&gt;

&lt;p&gt;Due to the complexity that using two different ports derives
(mainly due to NAT traversal), &lt;a href=&quot;https://tools.ietf.org/html/rfc5761&quot;&gt;RFC-5761&lt;/a&gt;
provides “an alternative to demultiplexing RTP and RTCP using separate UDP ports,
instead using only a single UDP port and demultiplexing within the application.”&lt;/p&gt;

&lt;p&gt;&lt;em&gt;That’s cool, how is this related to WebRTC?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;WebRTC media negotiation&lt;/em&gt; is based on Session Description Protocol
 (&lt;a href=&quot;https://tools.ietf.org/html/rfc4566&quot;&gt;SDP&lt;/a&gt;),
following the offer/answer model. To indicate the desire to multiplex RTP and RTCP packets,
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a=rtcp-mux&lt;/code&gt; attribute is used. This is (a partial) example of a SDP offer obtained in
&lt;a href=&quot;https://go.tu.com&quot;&gt;TU Go&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;...]
&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;rtcp:9 IN IP4 0.0.0.0
&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;sendrecv
&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;rtcp-mux
&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;rtpmap:111 opus/48000/2
&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;rtcp-fb:111 transport-cc
&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;fmtp:111 &lt;span class=&quot;nv&quot;&gt;minptime&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;10&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;useinbandfec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;rtpmap:106 CN/32000
&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;rtpmap:105 CN/16000
&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;rtpmap:13 CN/8000
&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;rtpmap:110 telephone-event/48000
&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;rtpmap:112 telephone-event/32000
&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;rtpmap:113 telephone-event/16000
&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;rtpmap:126 telephone-event/8000
&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;candidate:3455144793 1 udp 1685987071 95.23.241.104 62622 typ srflx raddr 192.168.1.131 rport 62622 generation 0 ufrag 9Che network-id 1 network-cost 10
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;...]&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In the example above, the offerer supports RTCP multiplexing.&lt;/p&gt;

&lt;p&gt;In the same way, the SDP answer should include as well the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a=rtcp-mux&lt;/code&gt; attribute to accept
RTCP multiplexing:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;...]
&lt;span class=&quot;nv&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;IN IP4 91.220.9.62
&lt;span class=&quot;nv&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0 0
&lt;span class=&quot;nv&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;audio 25384 UDP/TLS/RTP/SAVPF 111 110 106
&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;rtpmap:111 opus/48000/2
&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;fmtp:111 &lt;span class=&quot;nv&quot;&gt;useinbandfec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;minptime&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;10
&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;rtpmap:110 telephone-event/8000
&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;rtpmap:106 CN/8000
&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;ptime:20
&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;rtcp-mux
&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;rtcp:25384 IN IP4 91.220.9.62
&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;candidate:9711301045 1 udp 659136 91.220.9.62 25384 typ host generation 0&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;em&gt;That’s cool, how is this related to WebRTC?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;WebRTC NAT traversal&lt;/em&gt; is based on Interactive Connectivity Establishment methodology
(&lt;a href=&quot;https://tools.ietf.org/html/rfc5245&quot;&gt;ICE&lt;/a&gt;). While gathering candidates:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;if RTP and RTCP are sent on separate ports, connectivity checks are required for
both components.&lt;/li&gt;
  &lt;li&gt;if RTP and RTCP are multiplexed on the same port, only one connectivity check is required.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Negotiation for using RTP/RTCP multiplexing is done using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a=rtcp-mux&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a=rtcp:...&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a:candidate ...&lt;/code&gt; lines in both offer and answer.&lt;/p&gt;

&lt;p&gt;Bottom line, &lt;strong&gt;multiplexing RTP and RTCP reduces ICE overhead&lt;/strong&gt;, as it requires gathering less
candidates and it reduces the overhead in other parts of the VoIP architecture, e.g. less UDP
ports used in the TURN servers and less bandwidth wasted in connectivity checks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cool, so what’s next?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;XYZ&quot;&gt;PeerConnection&lt;/a&gt; constructor allows the application to specify global parameters for
the media session. Among them, &lt;strong&gt;the application can specify &lt;a href=&quot;https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-17#section-4.1.1&quot;&gt;its preferred policy
regarding use of RTP/RTCP multiplexing using one of the following policies&lt;/a&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;negotiate&lt;/em&gt;: includes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a=rtcp-mux&lt;/code&gt; attribute in the SDP, while gathering candidates
for both RTP and RTCP.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;require&lt;/em&gt;: includes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a=rtcp-mux&lt;/code&gt; attribute in the SDP, and gather only RTP candidates.
This cuts by half the number of candidates that the offerer needs to gather.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As defined in &lt;a href=&quot;https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-17&quot;&gt;Javascript Session Establishment Protocol&lt;/a&gt;,
“&lt;em&gt;the default multiplexing policy MUST be set to require&lt;/em&gt;”.&lt;/p&gt;

&lt;p&gt;In reality, the default multiplexing policy has always been &lt;em&gt;‘negotiate’&lt;/em&gt; in both Chrome and Firefox. But that’s changing in the near future.&lt;/p&gt;

&lt;p&gt;Starting in &lt;a href=&quot;https://groups.google.com/forum/#!topic/discuss-webrtc/eM57DEy89MY&quot;&gt;Chrome M57&lt;/a&gt;,
the &lt;a href=&quot;https://bugs.chromium.org/p/webrtc/issues/detail?id=6030&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rtcpMuxPolicy&lt;/code&gt; setting has gone from &lt;em&gt;negotiate&lt;/em&gt; to &lt;em&gt;require&lt;/em&gt;&lt;/a&gt;.
It should not create an issue if you’re doing peer to peer communications,
as browsers should be able to negotiate the RTP/RTCP multiplexing capability.
But it can indeed create issues if you’re using a WebRTC Gateway or expecting
RTCP candidates in your code for any reason. &lt;a href=&quot;https://medium.com/@nimbleape/webrtc-asterisk-and-chrome-57-a706fde33780#.iqiz2tmgx&quot;&gt;Nimble Ape describes an issue with Asterisk
interoperatibility&lt;/a&gt;,
as Asterisk does not support RTCP multiplexing.&lt;/p&gt;

&lt;p&gt;May you need to keep the old behaviour, you can explicitly set the policy to &lt;em&gt;negotiate&lt;/em&gt; while
creating the PeerConnection object.&lt;/p&gt;

&lt;p&gt;But please be aware that &lt;a href=&quot;https://groups.google.com/a/chromium.org/forum/#!msg/blink-dev/OP2SGSWF5lo/v7GOaWt_CQAJ&quot;&gt;there’s an intent to deprecate the &lt;em&gt;negotiate&lt;/em&gt;
option&lt;/a&gt;.
Chrome 58 will print a deprecation message if the rtcpMuxPolicy &lt;em&gt;negotiate&lt;/em&gt; is used. JSEP
says “Implementations MAY choose to reject attempts by the application to set the multiplexing
policy to “negotiate”, so be warned :smiley_cat:.&lt;/p&gt;

&lt;p&gt;What about Firefox? Firefox is still using the &lt;em&gt;negotiate&lt;/em&gt; rtcpMuxPolicy default value,
and there’s no way to specify the &lt;em&gt;require&lt;/em&gt; option while creating the PeerConnection object.
I’ve opened a ticket in &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1339203&quot;&gt;bugzilla&lt;/a&gt;
for tracking it.&lt;/p&gt;

&lt;p&gt;Happy media negotiation! :tiger:&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Docker and how to get access to insecure registries</title>
   <link href="http://juandebravo.com/2017/01/22/docker-insecure-registry/"/>
   <updated>2017-01-22T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2017/01/22/docker-insecure-registry/</id>
   <content type="html">&lt;p&gt;I just realized 2016 passed by and this blog didn’t get any update. I hope you were not worried about me! I’ve been fine! Just a bit busy :construction_worker:.&lt;/p&gt;

&lt;p&gt;Last two weeks I’ve been playing a bit with &lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt;. In general before getting your feet wet with a new technology, it’s convenient (required?) to either go through the &lt;a href=&quot;https://docs.docker.com/&quot;&gt;usually great documentation about the project&lt;/a&gt; or follow &lt;a href=&quot;https://harishnarayanan.org/writing/kubernetes-django/&quot;&gt;a tutorial&lt;/a&gt; about it. I did the later, and as a result of it I pushed my first two docker images to &lt;a href=&quot;https://hub.docker.com/r/juandebravo/&quot;&gt;Docker Hub&lt;/a&gt;. Nothing really impressive, but it helps you to go through the basics.&lt;/p&gt;

&lt;p&gt;Last week I started a side project and, for it to be more interesting, I decided to go with Docker and Kubernetes :neckbeard:. It turns out that the project cannot be public, so I needed to use an internal Docker hub we’re using in my current project for keeping it private.&lt;/p&gt;

&lt;p&gt;Unfortunately, that private Docker hub is configured to accept only HTTP requests, instead of HTTPS. I know… bear with me please :pray:.&lt;/p&gt;

&lt;p&gt;After tagging the image, I was trying to push to the docker hub repository and getting this response:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;fish&amp;gt; docker push &amp;lt;insecure-docker-hub-hostname&amp;gt;/&amp;lt;image-name&amp;gt;:&amp;lt;image-tag&amp;gt;
The push refers to a repository &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&amp;lt;insecure-docker-hub-hostname&amp;gt;/&amp;lt;image-name&amp;gt;]
Get https://&amp;lt;insecure-docker-hub-hostname&amp;gt;/v1/_ping: dial tcp &amp;lt;IP-address&amp;gt;:443: getsockopt: connection refused&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Console information shows that docker is trying to connect via HTTPS to docker hub.&lt;/p&gt;

&lt;p&gt;For overcoming this and get access via HTTP, you need to do the following:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you’re using Mac OSX Docker client&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Go to Docker -&amp;gt; Daemon -&amp;gt; Basic -&amp;gt; Insecure registries&lt;/li&gt;
  &lt;li&gt;Add &lt;insecure-docker-hub-hostname&gt; to the list&lt;/insecure-docker-hub-hostname&gt;&lt;/li&gt;
  &lt;li&gt;Restart Docker&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;If you’re using a Linux distribution&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Open file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/sysconfig/docker&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INSECURE_REGISTRY=&quot;--insecure-registry=&amp;lt;insecure-docker-hub-hostname&amp;gt; &quot;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Restart Docker&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now you’re ready to work with your insecure Docker hub!&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;fish&amp;gt; docker push &amp;lt;insecure-docker-hub-hostname&amp;gt;/&amp;lt;image-name&amp;gt;:&amp;lt;image-tag&amp;gt;
The push refers to a repository &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&amp;lt;insecure-docker-hub-hostname&amp;gt;/&amp;lt;image-name&amp;gt;]
...&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</content>
 </entry>
 
 <entry>
   <title>A virtual machine for WebRTC development</title>
   <link href="http://juandebravo.com/2015/11/23/webrtc-adapter-vagrant-box/"/>
   <updated>2015-11-23T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2015/11/23/webrtc-adapter-vagrant-box/</id>
   <content type="html">&lt;p&gt;As described in the &lt;a href=&quot;http://www.webrtc.org/&quot;&gt;WebRTC project main webpage&lt;/a&gt;, WebRTC is a free, open project that provides browsers and mobile applications with Real-Time Communications (RTC) capabilities via simple APIs. Or in case you prefer the &lt;a href=&quot;https://en.wikipedia.org/wiki/WebRTC&quot;&gt;Wikipedia definition&lt;/a&gt;, WebRTC (Web Real-Time Communication) is an API definition drafted by the World Wide Web Consortium (W3C) that supports browser-to-browser applications for voice calling, video chat, and P2P file sharing without the need of either internal or external plugins.&lt;/p&gt;

&lt;p&gt;WebRTC implements &lt;strong&gt;three basic new APIs&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;getUserMedia&lt;/strong&gt;: it represents synchronized streams of media.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;RTCPeerConnection&lt;/strong&gt;: it handles stable and efficient communication of streaming data between peers.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;DataChannel&lt;/strong&gt;: it enables peer-to-peer exchange of arbitrary data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;http://iswebrtcreadyyet.com/&quot;&gt;iswebrtcreadyyet&lt;/a&gt; lists the different WebRTC functionalities that are supported by the latest version of the most widely used browers.&lt;/p&gt;

&lt;p&gt;WebRTC APIs are still in early stages, which means that new browser versions could introdude non backwards compatible changes, and APIs name may be prefixed by a browser prefix (&lt;em&gt;moz&lt;/em&gt;, &lt;em&gt;webkit&lt;/em&gt;, …), which eventually means the JS developer is in charge on building a shim to support multiple browsers in her webRTC application.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/webrtc&quot;&gt;WebRTC team&lt;/a&gt; has created a &lt;strong&gt;&lt;a href=&quot;https://github.com/webrtc/adapter&quot;&gt;shim called adapter&lt;/a&gt;&lt;/strong&gt; as an effort for hiding those API changes and prefix differences from developers.&lt;/p&gt;

&lt;p&gt;In case you want to get started with &lt;strong&gt;adapter development&lt;/strong&gt;, you will need a &lt;a href=&quot;https://github.com/webrtc/adapter/tree/master/test&quot;&gt;Debian box to ensure you can run the multi-browser tests&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In order to make this process simpler, I have put some effort on creating a Vagrant box called &lt;a href=&quot;https://github.com/juandebravo/webrtc-box&quot;&gt;webrtc-box&lt;/a&gt;, that is in change of automating the development environment setup for working on WebRTC adapter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Running adapter tests should be as simple as&lt;/strong&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Clone repository&lt;/span&gt;
host &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone https://github.com/juandebravo/webrtc-box.git
host &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;webrtc-box
host &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;vagrant up

&lt;span class=&quot;c&quot;&gt;# Connect to guest machine&lt;/span&gt;
host &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;vagrant ssh

&lt;span class=&quot;c&quot;&gt;# Execute tests&lt;/span&gt;
vagrant@debian &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /adapter
vagrant@debian /adapter &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;npm &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And that’s it, you’re ready to start hacking on top of &lt;strong&gt;&lt;a href=&quot;https://github.com/webrtc/adapter&quot;&gt;adapter&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Happy webrtc-ing!!! :city_sunrise: :squirrel:&lt;/p&gt;

&lt;p&gt;In case you read this post before November 30th 2015, you’re on time for making a donation to our &lt;a href=&quot;http://moteam.co/tu-go&quot;&gt;Movember team&lt;/a&gt;!!! :man:&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Demystifying coroutines in python</title>
   <link href="http://juandebravo.com/2015/07/06/demystifying-coroutines-in-python/"/>
   <updated>2015-07-06T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2015/07/06/demystifying-coroutines-in-python/</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Coroutine&quot;&gt;Coroutines&lt;/a&gt; are &lt;em&gt;special functions&lt;/em&gt; that differ from &lt;em&gt;usual ones&lt;/em&gt; in four aspects:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;exposes several entry points to a function&lt;/strong&gt;. An entry point is the line of code inside the function where it will take control over the execution.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;can receive a different input&lt;/strong&gt; in every entry point while executing the coroutine.&lt;/li&gt;
  &lt;li&gt;can &lt;strong&gt;return different outputs&lt;/strong&gt; as response to the different entry points.&lt;/li&gt;
  &lt;li&gt;can &lt;strong&gt;save control state&lt;/strong&gt; between entry points calls.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Python implements coroutines starting in &lt;em&gt;Python 2.5&lt;/em&gt; by reusing the generator syntax&lt;/strong&gt;, as defined in &lt;a href=&quot;https://www.python.org/dev/peps/pep-0342/&quot;&gt;PEP 342 - Coroutines via Enhanced Generators&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Generator syntax is defined in &lt;a href=&quot;https://www.python.org/dev/peps/pep-0255/&quot;&gt;PEP 255 - Simple generators&lt;/a&gt;. I covered briefly the generator functionality in a &lt;a href=&quot;/2012/07/16/why-python-rocks/&quot;&gt;previous post&lt;/a&gt;. The basic usage of generators is creating an iterator over a data source. For example, the function in the snippet below returns a generator that iterates from a specific number down to 0, decreasing an unit in every iteration.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;countdown&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Counting down from %s to 0&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;i &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;countdown&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;5&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;:
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;     print i
...
Counting down from 5 to 0
5
4
3
2
1
0&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In the example above, the keyword &lt;strong&gt;yield&lt;/strong&gt; is used to return a new value in every iteration while &lt;em&gt;consuming&lt;/em&gt; the generator. It’s interesting to note that &lt;em&gt;a generator can be consumed only once&lt;/em&gt;, opposite to a list that can be consumed/iterate as much as needed. A generator is considered &lt;em&gt;exhausted&lt;/em&gt; upon being consumed the first time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://www.python.org/dev/peps/pep-0342/&quot;&gt;PEP 342&lt;/a&gt;&lt;/strong&gt; takes advantage of the keyword &lt;strong&gt;yield&lt;/strong&gt; for pointing out entry points where the function/coroutine will receive inputs while being executed. Let’s see a very simple example of a coroutine that
concatenates every string inserted by the user from the command line:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;concatenate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    Coroutine that receives a new string in every
    iteration and concatenates to the original one
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;temp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;temp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Wait for a new input (suspend the coroutine)...
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;temp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# ... and save control state (resume the execution)
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;_str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;temp&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_str&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Instantiate a new coroutine...
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;concatenate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;foo&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# ... and &quot;move&quot; the coroutine state till the `yield` keyword
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Send the raw input from the user to the coroutine...
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;raw_input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;StopIteration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# ... and capture the coroutine end by means
&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;# of StopIteration exception
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;What is really interesting is how the coroutine execution is suspended and resumed by means of the
&lt;strong&gt;yield&lt;/strong&gt; keyword, allowing the program flow to be moved from the coroutine to the external program
and back to it.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;python coroutine.py
bar
    foobar
bazz
    foobarbazz

    foobarbazz&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;May you be interested in additional information about this topic, I recommend going through &lt;a href=&quot;http://www.dabeaz.com/&quot;&gt;Daviz Beazley&lt;/a&gt; slides regarding &lt;a href=&quot;http://www.dabeaz.com/generators/Generators.pdf&quot;&gt;generators&lt;/a&gt; and &lt;a href=&quot;http://www.dabeaz.com/coroutines/Coroutines.pdf&quot;&gt;coroutines&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As a side project I have implemented a tiny library called &lt;strong&gt;&lt;a href=&quot;https://github.com/juandebravo/washington&quot;&gt;washington&lt;/a&gt;&lt;/strong&gt; that exposes a chainable API for building a coroutines stream. I had a lot of fun while digging into the implementation, even though the real usage of the library is expected to be very limited :blush:&lt;/p&gt;

&lt;p&gt;Happy coroutining!!! :bicyclist: :fireworks:&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Don't use YYYY in your date format template</title>
   <link href="http://juandebravo.com/2015/04/10/java-yyyy-date-format/"/>
   <updated>2015-04-10T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2015/04/10/java-yyyy-date-format/</id>
   <content type="html">&lt;p&gt;&lt;strong&gt;yyyy&lt;/strong&gt; is the pattern string to identify the year in the &lt;a href=&quot;http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html&quot;&gt;SimpleDateFormat&lt;/a&gt; class.&lt;/p&gt;

&lt;p&gt;Java 7 introduced &lt;strong&gt;YYYY&lt;/strong&gt; as a new date pattern to identify the &lt;em&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/ISO_week_date&quot;&gt;date week year&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;An average year is exactly 52.1775 weeks long, which means that eventually a year might have
either 52 or 53 weeks considering indivisible weeks.&lt;/p&gt;

&lt;p&gt;Using &lt;strong&gt;YYYY&lt;/strong&gt; &lt;em&gt;unintendedly&lt;/em&gt; while formatting a date can cause severe issues in your Java application.&lt;/p&gt;

&lt;p&gt;As an example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;    &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;java.util.Date&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;java.text.SimpleDateFormat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DataExample&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;date_s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2014-12-31&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;nc&quot;&gt;SimpleDateFormat&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleDateFormat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;yyyy-MM-dd&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
                &lt;span class=&quot;nc&quot;&gt;Date&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;date_s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
                &lt;span class=&quot;nc&quot;&gt;SimpleDateFormat&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dt1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleDateFormat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;YYYY&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
                &lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;And the year is... &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dt1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The snippet above prints “&lt;em&gt;And the year is… 2015&lt;/em&gt;”, because &lt;a href=&quot;http://www.epochconverter.com/date-and-time/weeknumbers-by-year.php?year=2014&quot;&gt;2015 week year started on 29/12/2014&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This issue seemed to be the root cause of the &lt;a href=&quot;http://tech.firstpost.com/news-analysis/twitter-suffers-massive-outage-on-all-online-platforms-back-now-247196.html&quot;&gt;massive outage that Twitter suffered last year&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So double check if you really need to use &lt;em&gt;YYYY&lt;/em&gt; while formatting your date, and in case of doubt… &lt;strong&gt;Better call Saul&lt;/strong&gt;!!&lt;/p&gt;

&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/7404XMzHr-M&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;
&lt;/iframe&gt;
</content>
 </entry>
 
 <entry>
   <title>Hanoi. Toggle functionalities in python</title>
   <link href="http://juandebravo.com/2015/02/15/toggle-func-in-python/"/>
   <updated>2015-02-15T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2015/02/15/toggle-func-in-python/</id>
   <content type="html">&lt;p&gt;Upon deploying a new version of your product into production,
 it’s usually handy to enable the new functionalities only to
 a subset of users. This allows to measure the impact of your
 code changes in a controlled way:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Does the new functionality have an &lt;em&gt;unexpected impact in
server performance&lt;/em&gt; that was not detected in stress testing lab?&lt;/li&gt;
  &lt;li&gt;Is the new functionality &lt;em&gt;increasing session duration&lt;/em&gt;, global
product usage, &lt;em&gt;customer satisfaction&lt;/em&gt;, etc?&lt;/li&gt;
  &lt;li&gt;Whas is the impact on the client side? Is it creating a
battery drain or any other unexpected issue?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feature toggling can be handy as well to &lt;em&gt;reduce the impact of
 dependencies among components&lt;/em&gt;. If a new functionality in &lt;em&gt;component A&lt;/em&gt;
 requires a new version of &lt;em&gt;component B&lt;/em&gt;, the new functionality in
 component A can be toggle off till the new B version reaches production,
 then the &lt;strong&gt;deployment pipeline is loosely coupled&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Over my last Christmas holidays I spent some time visiting Vietnam,
 and back then I read about &lt;a href=&quot;https://github.com/FetLife/rollout&quot;&gt;rollout gem&lt;/a&gt;,
 a ruby library that implements feature toggling using Redis as backend.
 &lt;a href=&quot;https://github.com/asenchi/proclaim&quot;&gt;proclaim&lt;/a&gt; python port is kind
 of outdated so I decided to build another python port, that has been
 named as &lt;a href=&quot;https://github.com/juandebravo/hanoi&quot;&gt;hanoi&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hanoi&lt;/strong&gt; can be used for the following scenarios:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Enable/disable globally a functionality (toggle on/off)&lt;/li&gt;
  &lt;li&gt;Enable a functionality to a percentage of users, increasing
the percentage gradually to ensure server and client behaviour.&lt;/li&gt;
  &lt;li&gt;Enable a functionality to specific users (whitelist users)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Currently three BackEnd are implemented (a memory based backend and
 REDIS backend in two different flavors). My expectation is to
 include additional BackEnds in the future to support additional
 storages, such as &lt;a href=&quot;http://memcached.org/&quot;&gt;memcached&lt;/a&gt;
 and &lt;a href=&quot;http://www.mongodb.org/&quot;&gt;mongoDB&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For additional information about hanoi check the documentation in the &lt;a href=&quot;https://github.com/juandebravo/hanoi#hanoi&quot;&gt;github repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy deploying! :hammer:&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;Hanoi&quot; style=&quot;width: 100%; padding: 0&quot; src=&quot;/gfx/hanoi.jpg&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Validating Arity in JavaScript</title>
   <link href="http://juandebravo.com/2015/01/23/validate-arity/"/>
   <updated>2015-01-23T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2015/01/23/validate-arity/</id>
   <content type="html">&lt;p&gt;Last week I was discussing with my pals &lt;a href=&quot;http://www.pollinimini.net&quot;&gt;@drslump&lt;/a&gt;
 and &lt;a href=&quot;http://www.ladybenko.net/&quot;&gt;@ladybenko&lt;/a&gt; about a very simple idea I came up
 with while reading &lt;a href=&quot;http://ejohn.org/about/&quot;&gt;John Resig&lt;/a&gt;
 &lt;a href=&quot;http://ejohn.org/blog/secrets-of-the-javascript-ninja-released/&quot;&gt;Secrets of the JavaScript Ninja&lt;/a&gt; book on Christmas holidays.&lt;/p&gt;

&lt;p&gt;The idea is very simple: ensure that a function is called with the expected number of parameters.&lt;/p&gt;

&lt;p&gt;A function defined like:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fullName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fullName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;surname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;surname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;could be called with:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;zero parameters&lt;/strong&gt;: &lt;em&gt;name&lt;/em&gt; and &lt;em&gt;surname&lt;/em&gt; will be undefined.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;one parameter&lt;/strong&gt;: the parameter will be assigned to &lt;em&gt;name&lt;/em&gt;, &lt;em&gt;surname&lt;/em&gt; will be undefined.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;two parameters&lt;/strong&gt;: the former parameter will be assigned to &lt;em&gt;name&lt;/em&gt;, the latter to &lt;em&gt;surname&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;three or more parameters&lt;/strong&gt;: the first two parameters will be assigned to &lt;em&gt;name&lt;/em&gt; and &lt;em&gt;surname&lt;/em&gt; respectively, the next ones could be accessed via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arguments&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You might want to ensure the function is always called with two parameters, so scenarios like this one won’t happen:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;fullName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Foo undefined&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Let’s do the magic by defining a method in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Function prototype&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nb&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;validateArity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;validateArity&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;arguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;arguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Arity was &amp;lt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;arguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;gt; but expected &amp;lt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Simply adding to our previous function the following:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fullName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fullName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;surname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;surname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;validateArity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Correct call&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fullName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Bar&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Bar&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Incorrect call&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fullName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Arity&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;was&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;but&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;expected&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;Protip&lt;/strong&gt;: adding a function to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Function prototype&lt;/code&gt; is usually NOT a good idea.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Using travis-ci to build this blog</title>
   <link href="http://juandebravo.com/2014/11/22/using-travis-ci-to-build-this-blog/"/>
   <updated>2014-11-22T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2014/11/22/using-travis-ci-to-build-this-blog/</id>
   <content type="html">&lt;p&gt;This &lt;a href=&quot;/2012/05/31/yet-another-blog-in-the-world/&quot;&gt;blog is built&lt;/a&gt; using Jekyll as static code site generator and GitHub as the deployment target thanks to its support to Jekyll via GitHub pages.&lt;/p&gt;

&lt;p&gt;One of the great things about using GitHub together with Jekyll is the support that GitHub provides out of the box to generate your HTML pages using Jekyll in the server side whenever a new content is added to your repository.&lt;/p&gt;

&lt;p&gt;Some months ago I ran some experiments to include &lt;em&gt;emojis support&lt;/em&gt; to this blog :smile:. Jekyll
supports a plugin mechanism to extend the framework functionality.&lt;/p&gt;

&lt;p&gt;Bad news are that GitHub does not allow third-party plugins to build your Jekyll based web page, like this
one. The reason behind this might be to avoid any kind of attack from a malicious user. Then I needed to either build the site locally and upload the HTML version to GitHub, or get rid of emojies.&lt;/p&gt;

&lt;p&gt;I have been working on local compiling over the last months, but some weeks ago I started playing with &lt;em&gt;&lt;a href=&quot;http://travis-ci.org&quot;&gt;travis&lt;/a&gt;&lt;/em&gt; to remove this boring work from my side. Those are the relevant steps that I did:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Create a new account in Travis&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Configure your GitHub project to support &lt;em&gt;travis&lt;/em&gt;. &lt;a href=&quot;https://developer.github.com/webhooks/#services&quot;&gt;Here&lt;/a&gt; you can find the list of supported services &amp;amp; webhooks (&lt;a href=&quot;https://api.github.com/hooks&quot;&gt;JSON format&lt;/a&gt;).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Install the &lt;em&gt;travis&lt;/em&gt; gem in your local environment&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;gem &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;travis&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Generate a valid token in the GitHub project settings page.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Hash the token for travis to be able to use it in a secured way (as the value will be included in your repository)&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;travis encrypt &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; &amp;lt;USER&amp;gt;/&amp;lt;REPOSITORY&amp;gt; &lt;span class=&quot;nv&quot;&gt;GH_TOKEN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&amp;lt;GH-TOKEN&amp;gt; &lt;span class=&quot;nt&quot;&gt;--add&lt;/span&gt; env.global&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://docs.travis-ci.com/&quot;&gt;Configure your build&lt;/a&gt; in the &lt;strong&gt;.travis.yaml&lt;/strong&gt; file at the root of your repository.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;In order to use a GitHub OAuth token, &lt;a href=&quot;https://github.com/juandebravo/juandebravo.github.com/blob/master/.travis.yml#L36&quot;&gt;the configured URL should be the HTTPS one&lt;/a&gt;:&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;git remote set-url origin https://&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;GH_TOKEN&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;@github.com/juandebravo/juandebravo.github.com.git&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;ul&gt;
  &lt;li&gt;Run the command &lt;em&gt;travis-lint&lt;/em&gt; to validate the file syntax.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;&lt;a href=&quot;http://travis-ci.org&quot;&gt;Travis&lt;/a&gt;&lt;/em&gt; is a great piece of software that you can take advantage of very easily!! :bowtie: :neckbeard:&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Registering subclasses in python and ruby</title>
   <link href="http://juandebravo.com/2014/03/12/registering-subclasses-in-python-and-ruby/"/>
   <updated>2014-03-12T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2014/03/12/registering-subclasses-in-python-and-ruby/</id>
   <content type="html">&lt;p&gt;Some years ago while I was contributing to the awesome Open Source project &lt;a href=&quot;http://adhearsion.com/&quot;&gt;Adhearsion&lt;/a&gt;, we decided to split the logic contained in 1.0 version into different modules that might be loaded by the developer when needed. &lt;a href=&quot;https://github.com/adhearsion/adhearsion/tree/v1.2.5&quot;&gt;Adhearsion 1.0&lt;/a&gt; was tightly coupled with gems like activerecord and activesupport, which were not required for the framework basic functionality and did not provide any real value to most of the Adhearsion applications. Decoupling the logic allowed developers to include only the required dependencies in their applications.&lt;/p&gt;

&lt;p&gt;As result of this exercise, different gems were developed to provide isolated functionalities, like &lt;a href=&quot;https://github.com/adhearsion/adhearsion-activerecord&quot;&gt;adhearsion-activerecord&lt;/a&gt; builds the bridge to use &lt;a href=&quot;https://github.com/rails/rails/tree/master/activerecord&quot;&gt;ActiveRecord&lt;/a&gt; in an Adhearsion application.&lt;/p&gt;

&lt;p&gt;Besides the primary goal of decoupling logic, developers should be able as well to create their own modules to extend the base functionality provided by &lt;a href=&quot;http://adhearsion.com/&quot;&gt;Adhearsion&lt;/a&gt;. Those modules were called &lt;strong&gt;plugins&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;While thinking about how to build this plugin functionality, I dug into different libraries trying to find a clean solution, and &lt;a href=&quot;http://rubyonrails.org/&quot;&gt;Rails&lt;/a&gt; came to the rescue. The developer that is using Rails can define her own plugins to extend the functionality of the framework or modify its initialization. These plugins are called &lt;strong&gt;&lt;a href=&quot;http://api.rubyonrails.org/classes/Rails/Railtie.html&quot;&gt;Railties&lt;/a&gt;&lt;/strong&gt;. Creating a Railtie is really simple:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;inherit from &lt;a href=&quot;http://api.rubyonrails.org/classes/Rails/Railtie.html&quot;&gt;Railtie&lt;/a&gt; class.&lt;/li&gt;
  &lt;li&gt;load your class during the Rails boot process.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But… how does Rails know that it should execute the code defined in the Railtie subclass while boosting itself? The trick is based on a cool feature from the Ruby language, which defines a hook in the &lt;a href=&quot;http://www.ruby-doc.org/core-2.1.0/Class.html#method-i-inherited&quot;&gt;parent class&lt;/a&gt; that is raised every time the class is inherited. &lt;a href=&quot;https://github.com/rails/rails/blob/master/railties/lib/rails/railtie.rb#L129-L133&quot;&gt;Here&lt;/a&gt; you can see the snippet of code that builds the Railtie magic.&lt;/p&gt;

&lt;p&gt;Eventually, for &lt;a href=&quot;https://github.com/adhearsion/adhearsion/blob/develop/lib/adhearsion/plugin.rb&quot;&gt;Adhearsion plugins&lt;/a&gt; I followed the same rule.&lt;/p&gt;

&lt;p&gt;Find below two snippets of code that registers a list of subclasses in both ruby and python.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Plugin&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;inherited&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;registry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;registry&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@registry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;registry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Plugin&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Bar&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Plugin&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Plugin subclasses: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Plugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:to_s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;, &apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Registry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bases&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;hasattr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;registry&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# Parent class
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;cls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;registry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# Child class
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;cls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;registry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Registry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bases&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Plugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;__metaclass__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Registry&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Plugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;Bar&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;Bar&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Plugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Plugin subclasses: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;, &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Plugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;registry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The output of both scripts is:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;Plugin subclasses: Foo, Bar&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Happy coding! :kissing_cat:&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Class and static methods in python</title>
   <link href="http://juandebravo.com/2014/03/08/python-class-and-static-methods/"/>
   <updated>2014-03-08T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2014/03/08/python-class-and-static-methods/</id>
   <content type="html">&lt;p&gt;Last week we had a nice conversation during a python code review about when class and static methods should be used, or either they should not be used at all.&lt;/p&gt;

&lt;p&gt;Find below my opinions around this topic, feel free to comment and bring some discussion :satisfied:.&lt;/p&gt;

&lt;p&gt;In general, you should think about &lt;strong&gt;moving a class or static method to the module&lt;/strong&gt; that holds the class definition. As you may well know, functions are first class citizens in python:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;VALUES&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;1&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;2&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;3&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;

    &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;staticmethod&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VALUES&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This snippet can be refactored to:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_foo_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;VALUES&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;VALUES&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;1&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;2&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;3&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Some exception that might apply:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;The class provides several staticmethod to validate attributes, retrieve class information, etc. Moving all these methods might fill up the module with too many definitions that are clearly tight to a specific class.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The module holds several classes&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;You want to define an &lt;em&gt;auxiliar method&lt;/em&gt; to create an instance, and you want the childs to be able to override the initialization (think if you should use composition instead of inheritance!):&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;PROPERTIES&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;name&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;john&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;s&quot;&gt;&apos;surname&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;doe&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;s&quot;&gt;&apos;age&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;28&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;s&quot;&gt;&apos;email&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;john@pollinimini.net&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;

    &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;classmethod&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;from_properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ins&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iteritems&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;ins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ins&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__str__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;, &apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__dict__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;

    &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;classmethod&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;from_properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ins&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from_properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deferred&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ins&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from_properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PROPERTIES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from_properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PROPERTIES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The output of the program is:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;age, surname, name, email
deferred, age, surname, name, email&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;Bar&lt;/strong&gt; includes an additional attribute to the instance, but the preliminar instance initilization is similar to what &lt;strong&gt;Foo&lt;/strong&gt; does.&lt;/p&gt;

&lt;p&gt;There are other alternatives to the class method in this case though:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;defining a &lt;strong&gt;factory class&lt;/strong&gt; to return the proper class.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;define a function that receives as parameter a function to be applied while defining the instance:&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;PROPERTIES&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;name&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;john&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;s&quot;&gt;&apos;surname&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;doe&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;s&quot;&gt;&apos;age&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;28&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;s&quot;&gt;&apos;email&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;john@pollinimini.net&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create_foo_with_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ins&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from_properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ins&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;

    &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;classmethod&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;from_properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ins&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;properties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iteritems&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;ins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__setattr__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ins&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__str__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;, &apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__dict__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;


&lt;span class=&quot;c1&quot;&gt;# Create a Foo instance
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create_foo_with_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PROPERTIES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Create a Bar instance
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create_foo_with_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PROPERTIES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                               &lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__setattr__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;deferred&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Happy coding! :kissing_cat:&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Building an automatic initializer in python</title>
   <link href="http://juandebravo.com/2014/01/04/python-auto-initializer/"/>
   <updated>2014-01-04T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2014/01/04/python-auto-initializer/</id>
   <content type="html">&lt;p&gt;One of the cool things of Scala is that, in general, you don’t need to write a lot of boilerplate while doing things in the “normal way”.&lt;/p&gt;

&lt;p&gt;As an example, while defining a class which constructor requires one or more arguments, there’s no need to assign the parameters to instance attributes, this is done out of the box by the compiler while creating the Java code:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scala&quot; data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;bar&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;bazz&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//&amp;gt; bar&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Python, like many other languages, does not behave that way, therefore you must assign the attributes to instance variables. Someone would argue that this is indeed the pythonic way to work, &lt;a href=&quot;http://www.python.org/dev/peps/pep-0020/&quot;&gt;making things as explicit as possible&lt;/a&gt;. Letting aside that the method &lt;a href=&quot;http://docs.python.org/2/reference/datamodel.html#object.__init__&quot;&gt;__init__&lt;/a&gt; is not a constructor, you can do the assigment with the following snippet of code:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;bar&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;bazz&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It turns out that a high percentage of the time, the only thing you may need to do in your __init__ methods is assigning the parameters to instance variables.  Being a common behavior, it seems to me like a nice chance to build a
&lt;a href=&quot;2012/07/24/why-python-rocks_and_two/&quot;&gt;decorator&lt;/a&gt; :smile_cat:. Here it goes:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;inspect&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;autoinit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;co_varnames&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;func_code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_varnames&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;kwa_defaults&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inspect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getargspec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;defaults&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_wrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nargs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;names&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;co_varnames&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;kwa_keys&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;co_varnames&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;nargs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;names&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)])&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;names&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Add the keyword arguments
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kwa_keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;nargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kwa_defaults&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwa_keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# Set the values to the instance attributes
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iteritems&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;setattr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_wrap&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The function that builds the decorator (autoinit) is doing simple things:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;retrieve the parameter names and the default keyword parameter values&lt;/li&gt;
  &lt;li&gt;build a function, which is the value returned by the function autoinit, which will inspect both args and kwargs while creating a new instance object, retrieve the actual value for every parameter, and assign them to instance attributes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An usage example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;

    &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;autoinit&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</content>
 </entry>
 
 <entry>
   <title>Encoding exercise in python</title>
   <link href="http://juandebravo.com/2013/09/11/encoding-exercise-in-python/"/>
   <updated>2013-09-11T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2013/09/11/encoding-exercise-in-python/</id>
   <content type="html">&lt;p&gt;Unicode and encodings is always a fun thing. This script encodes an input string using different encodings and shows the output length:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# -*- coding: utf-8 -*-
&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sys&lt;/span&gt;
 
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;code_points&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;unicode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;utf-8&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Testing values
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;code_points&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\U0001F37A\U00000045\U0000039B&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\U0001F37A&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
 
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;handle_encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code_point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;                                                                        
        &lt;span class=&quot;n&quot;&gt;values&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;{:&amp;gt;15}&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;                                      
                  &lt;span class=&quot;s&quot;&gt;&apos; ---&amp;gt; &apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;                                                     
                  &lt;span class=&quot;s&quot;&gt;&apos;:&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;{0:x}&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt;                      
                  &lt;span class=&quot;n&quot;&gt;code_point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;                                   
                  &lt;span class=&quot;s&quot;&gt;&apos; (&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;code_point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;)&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;               
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;                                                   
    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;                                                     
        &lt;span class=&quot;n&quot;&gt;values&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;{:&amp;gt;15}&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;                                      
                  &lt;span class=&quot;s&quot;&gt;&apos; ---&amp;gt; &apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;                                                     
                  &lt;span class=&quot;s&quot;&gt;&apos;Unable to encode the codepoint in {0}&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;       
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  
 
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code_point&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code_points&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;{:&amp;gt;15}&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;character&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos; ---&amp;gt; &apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code_point&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;{:&amp;gt;15}&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;code points&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos; ---&amp;gt; &apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;repr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;code_point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;coding&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;ascii&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;latin-1&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;utf-8&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;utf-16&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;utf-16be&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;utf-16le&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;handle_encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;coding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code_point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;python encoding.py &lt;span class=&quot;s2&quot;&gt;&quot;OLA KE ASE&quot;&lt;/span&gt;
      character &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; OLA KE ASE
    code points &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; u&lt;span class=&quot;s1&quot;&gt;&apos;OLA KE ASE&apos;&lt;/span&gt;
          ascii &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 4f:4c:41:20:4b:45:20:41:53:45 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;10&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        latin-1 &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 4f:4c:41:20:4b:45:20:41:53:45 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;10&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
          utf-8 &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 4f:4c:41:20:4b:45:20:41:53:45 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;10&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
         utf-16 &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; ff:fe:4f:0:4c:0:41:0:20:0:4b:0:45:0:20:0:41:0:53:0:45:0 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;22&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
       utf-16be &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 0:4f:0:4c:0:41:0:20:0:4b:0:45:0:20:0:41:0:53:0:45 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;20&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
       utf-16le &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 4f:0:4c:0:41:0:20:0:4b:0:45:0:20:0:41:0:53:0:45:0 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;20&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Happy encoding :monkey:&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>JavaScript, perform multiple operations in parallel</title>
   <link href="http://juandebravo.com/2013/03/31/javascript-perform-multiple-operations-in-parallel/"/>
   <updated>2013-03-31T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2013/03/31/javascript-perform-multiple-operations-in-parallel/</id>
   <content type="html">&lt;p&gt;I’ve spent bits of my spare time over the last weeks improving my JavaScript skills. I’ve read &lt;a href=&quot;http://effectivejs.com/&quot;&gt;Effective JavaScript: 68 Specific Ways to Harness the Power of JavaScript&lt;/a&gt;, by &lt;a href=&quot;https://twitter.com/littlecalculist&quot;&gt;David Herman&lt;/a&gt;; I highly recommend this book to any who wants to dig deeper into this language.&lt;/p&gt;

&lt;p&gt;Last Thursday my pal &lt;a href=&quot;https://twitter.com/rafeca&quot;&gt;@rafeca&lt;/a&gt; raised an interesting question: &lt;strong&gt;how could we start two or more asynchronous operations in JavaScript and execute a callback upon all of them are finished, but not before?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One of the latest chapters of the mentioned book comes up with the answer: store responses in an ordered array and execute the callback when every response has been received (there are no pending operations).&lt;/p&gt;

&lt;p&gt;Let’s see an specific example: &lt;strong&gt;retrieve a set of user profiles from a third party database and print the result in an HTML table only when all of them have been received&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In the following five steps we’ll figure out how to resolve this:&lt;/p&gt;

&lt;h1 id=&quot;1--create-the-html-skeleton-to-print-the-user-profiles&quot;&gt;1.- Create the HTML skeleton to print the user profiles&lt;/h1&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;thead&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
              &lt;span class=&quot;nt&quot;&gt;&amp;lt;th&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Name&lt;span class=&quot;nt&quot;&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
              &lt;span class=&quot;nt&quot;&gt;&amp;lt;th&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;profile&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Profile&lt;span class=&quot;nt&quot;&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/thead&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;tbody&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;profiles&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/tbody&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;error&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;2--create-a-simple-function-to-retrieve-user-profiles&quot;&gt;2.- Create a simple function to retrieve user profiles&lt;/h1&gt;

&lt;p&gt;For the sake of simplicity, I’ve mocked the profile database using an in-memory dictionary:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Profile&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;profile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;profile&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;profile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ProfileDB&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;users&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;john&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Profile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;john&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;manager&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;mark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Profile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;mark&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;developer&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;thomas&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Profile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;thomas&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;QA&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_getUserProfile&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;profile&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;profile&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;profile &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; not found&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;c1&quot;&gt;// simulate a random delay between 0 and 1 seconds&lt;/span&gt;
                    &lt;span class=&quot;nx&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;profile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;getUserProfile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_getUserProfile&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;})();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;3--create-a-function-to-retrieve-a-set-of-users-profile-and-execute-a-callback-upon-every-profile-retrieval&quot;&gt;3.- Create a function to retrieve a set of users profile and execute a callback upon every profile retrieval&lt;/h1&gt;

&lt;p&gt;In this step we’re building the function that will start in parallel the required operations and execute the relevant callback (success or error in case of any failure):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;getUserProfiles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;onsuccess&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;onerror&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// number of pending operations&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;pending&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// store results in this array&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pending&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// execute callback if users is empty&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;onsuccess&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;ProfileDB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getUserProfile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;profile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;profile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;pending&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pending&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;c1&quot;&gt;// every profile has been retrieved, execute callback&lt;/span&gt;
                &lt;span class=&quot;nx&quot;&gt;onsuccess&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// execute error callback&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;onerror&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;4--create-the-client-to-retrieve-a-list-of-user-profiles&quot;&gt;4.- Create the client to retrieve a list of user profiles&lt;/h1&gt;

&lt;p&gt;Step 4 creates the client that will use the function created in step 3. We need to provide callbacks for both success and error scenearios. Upon success, users profile are printed in the HTML skeleton built in step 1. In case of error, the specific message is shown in the div element:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;userElement&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;profile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;tr&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;td&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createTextNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_profile&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;td&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;_profile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createTextNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;profile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_profile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;getUserProfiles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;john&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;mark&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;thomas&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;profiles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fragment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createDocumentFragment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;profiles&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;profiles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;profile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;fragment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;userElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;profile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;profile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;profile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;profiles&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fragment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cloneNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;innerHTML&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createTextNode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;5--run-it&quot;&gt;5.- Run it&lt;/h1&gt;

&lt;p&gt;In this case we’re updating the DOM just once, upon retrieving the three users profile. This doesn’t provide a high advantage, but if we’re retrieving hundreds of elements, updating the DOM in any response may reduce significantly our application performance :squirrel:.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>SBT run&#58; choose automatically the App to launch</title>
   <link href="http://juandebravo.com/2012/12/30/sbt-run-select-main-class/"/>
   <updated>2012-12-30T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2012/12/30/sbt-run-select-main-class/</id>
   <content type="html">&lt;p&gt;I like Christmas because, beside resting from work and having fun with family and friends, usually there is time to learn something new. During this Xmas I’ve been playing with Scala: First, trying to finish the &lt;a href=&quot;https://class.coursera.org/progfun-2012-001/auth/auth_redirector?type=login&amp;amp;subtype=normal&quot;&gt;Coursera Functional Programming Principles course&lt;/a&gt;. Later, working a bit in a personal project. Better late than never :smile&lt;/p&gt;

&lt;p&gt;As for my personal project, it provides more than one &lt;strong&gt;executable entry point&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;web application exposing a REST API using &lt;a href=&quot;http://www.scalatra.org/&quot;&gt;Scalatra&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;offline script to retrieve data from a third party periodically. This could be easily done with &lt;a href=&quot;http://rake.rubyforge.org/&quot;&gt;Rake&lt;/a&gt; in the Ruby world, and as far as I know there’s not a &lt;a href=&quot;http://code.activestate.com/pypm/search:rake/&quot;&gt;task management tool “de facto standard” in python&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Working with Scala and SBT, the command &lt;strong&gt;sbt run&lt;/strong&gt; looks like the natural alternative. It seeks for every Scala Object in the project that could be used as the assembly entry point:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;an object that defines a main method&lt;/li&gt;
  &lt;li&gt;an object that inherits from App&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your application has more than one object fitting the previous requirement, the command &lt;em&gt;sbt run&lt;/em&gt; will ask for your help to finish the execution.&lt;/p&gt;

&lt;p&gt;Let’s consider the following snippet of code, having two objects that define a &lt;em&gt;main&lt;/em&gt; method:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scala&quot; data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;k&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;File&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;scala&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello from Foo&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;File&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Bar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;scala&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Bar&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello from Bar&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;When you execute the &lt;strong&gt;sbt run&lt;/strong&gt; command, the following text shows up:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; sbt run

Multiple main classes detected, &lt;span class=&quot;k&quot;&gt;select &lt;/span&gt;one to run:

 &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;1] Bar
 &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;2] Foo

Enter number: 2
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;info] Running Foo
Hello from Foo
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;success] Total &lt;span class=&quot;nb&quot;&gt;time&lt;/span&gt;: 29 s, completed Dec 30, 2012 11:36:28 PM&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It requires human action (in the previous example, fill in the number &lt;em&gt;2&lt;/em&gt;), as the &lt;em&gt;run&lt;/em&gt; command does not receive any parameter to automate the process.&lt;/p&gt;

&lt;p&gt;Fortunately, there’s an easy solution using the SBT plugin &lt;a href=&quot;https://github.com/sbt/sbt-start-script&quot;&gt;sbt-start-script&lt;/a&gt; :squirrel:. You just need to follow these three steps:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Create (or update) the file &lt;em&gt;project/plugins.sbt&lt;/em&gt;, including:&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scala&quot; data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;nf&quot;&gt;addSbtPlugin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;com.typesafe.sbt&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;sbt-start-script&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;0.6.0&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;ul&gt;
  &lt;li&gt;Create (or update) the file &lt;em&gt;build.sbt&lt;/em&gt;, adding:&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scala&quot; data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;com.typesafe.sbt.SbtStartScript&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;seq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SbtStartScript&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;startScriptForClassesSettings&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;ul&gt;
  &lt;li&gt;Execute:&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;sbt update
sbt start-script&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;As result, a new file &lt;strong&gt;target/start&lt;/strong&gt; is created. A file that requires the main class name to be executed as the first argument:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; target/start Foo
Hello from Foo

&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; target/start Bar
Hello from Bar&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Two last tips:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;In case your program just has a single main class, the script does not require any argument.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Remember to add the automatically generated file &lt;em&gt;target/start&lt;/em&gt; to your CVS&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>About git internals</title>
   <link href="http://juandebravo.com/2012/12/01/git-internals-lecture/"/>
   <updated>2012-12-01T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2012/12/01/git-internals-lecture/</id>
   <content type="html">&lt;p&gt;Last week, &lt;a href=&quot;https://twitter.com/search?q=%23Devcon1&amp;amp;src=typd&quot;&gt;the first Telefonica Digital Developers Conference&lt;/a&gt; was held in Madrid.
A two day event that gathered the Spain based developer team. 48 hours of lectures and constant knowledge sharing.&lt;/p&gt;

&lt;p&gt;My talk, “git internals”, highlighted how git repository works when storing relevant information.&lt;/p&gt;

&lt;center&gt;
&lt;iframe src=&quot;http://www.slideshare.net/slideshow/embed_code/15439276&quot; width=&quot;427&quot; height=&quot;356&quot; frameborder=&quot;0&quot; marginwidth=&quot;0&quot; marginheight=&quot;0&quot; scrolling=&quot;no&quot; style=&quot;border:1px solid #CCC;border-width:1px 1px 0;margin-bottom:5px&quot; allowfullscreen=&quot;&quot; webkitallowfullscreen=&quot;&quot; mozallowfullscreen=&quot;&quot;&gt; &lt;/iframe&gt;
&lt;/center&gt;
</content>
 </entry>
 
 <entry>
   <title>Emoji support in jekyll</title>
   <link href="http://juandebravo.com/2012/11/17/emoji-support-in-jekyll/"/>
   <updated>2012-11-17T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2012/11/17/emoji-support-in-jekyll/</id>
   <content type="html">&lt;p&gt;While writing my &lt;a href=&quot;/2012/10/28/css-changes/&quot;&gt;last post&lt;/a&gt; I seeked for information about how to include plugins in Jekyll. &lt;a href=&quot;https://github.com/mojombo/jekyll/wiki/Plugins&quot;&gt;Jekyll repo wiki&lt;/a&gt; describes how easy is to write and hook specific logic to your Jekyll site.&lt;/p&gt;

&lt;p&gt;Nonetheless, if you are using Github as hosting to deploy your Jekyll site, you cannot use plugins :worried:.&lt;/p&gt;

&lt;h2 id=&quot;1-include-the-gemoji-dependency-in-your-gemfile&quot;&gt;1. Include the &lt;strong&gt;gemoji&lt;/strong&gt; dependency in your Gemfile&lt;/h2&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;gem&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;gemoji&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:require&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;emoji/railtie&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;2-add-a-configuration-attribute-in-the-_configyml-file&quot;&gt;2. Add a configuration attribute in the &lt;strong&gt;_config.yml&lt;/strong&gt; file&lt;/h2&gt;

&lt;p&gt;This folder will contain the emoji icons.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;na&quot;&gt;emoji&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;    &lt;span class=&quot;s&quot;&gt;gfx/emoji&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;3-write-a-rake-task-into-the-rakefile&quot;&gt;3. Write a rake task into the Rakefile&lt;/h2&gt;

&lt;p&gt;This rake task copies the icons included in the gemoji gem into your Jekyll site folder. It also generates a CSS file.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;Generate emoji CSS styles&apos;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:emoji&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;green&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;Generating emoji CSS...&apos;&lt;/span&gt;

  &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;jekyll&apos;&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;site&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Jekyll&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Site&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Jekyll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;configuration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({}))&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;site&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;emoji&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;empty?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;exists?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;exists?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/smiley.png&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;_css&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%[.emoji {
  width: 20px;
  display: inline-block;
  text-indent: -2000px;
}

]&lt;/span&gt;

    &lt;span class=&quot;no&quot;&gt;Dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Emoji&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;images_path&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/emoji/*.png&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;FileUtils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cp&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;emoji_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;_css&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%[.emoji_#{emoji_name.join(&quot;.&quot;)} {
  background:url(&quot;/#{path}/#{file}&quot;) no-repeat scroll 0 center transparent;
  background-size: 20px auto;
}

]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;css/emoji.css&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;w+&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_css&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;green&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;Done!&apos;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;4-execute-the-rake-task&quot;&gt;4. Execute the rake task&lt;/h2&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;rake emoji&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now you can check the generated CSS file that defines a specific style per emoji icon and the &lt;strong&gt;png&lt;/strong&gt; files (the emoji icons) copied into the configured folder.&lt;/p&gt;

&lt;h2 id=&quot;5-include-the-generated-css-file-into-html-layouts&quot;&gt;5. Include the generated CSS file into HTML layouts&lt;/h2&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;stylesheet&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/css/style.css&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;6-write-a-plugin-that-converts-the-emoji-tags-in-html-tags&quot;&gt;6. Write a plugin that converts the emoji tags in HTML tags&lt;/h2&gt;

&lt;p&gt;Copy this content into the file &lt;strong&gt;_plugins/emoji.rb&lt;/strong&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;gemoji&quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Jekyll&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;EmojiFilter&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;emojify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;registers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:site&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;emoji&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;gsub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/:([a-z0-9\+\-_]+):/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Emoji&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;names&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;include?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;span class=&apos;emoji emoji_&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&apos;&amp;gt;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; emoji&amp;lt;/span&amp;gt;&quot;&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;match&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# emojify&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# EmojiFilter&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Jekyll&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Liquid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register_filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Jekyll&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EmojiFilter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;7-emojify-your-content&quot;&gt;7. Emojify your content!&lt;/h2&gt;

&lt;p&gt;Concat the filter &lt;strong&gt;emojify&lt;/strong&gt; in the layouts where you want to include emojies.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;post&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;role=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;main&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;header&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;h2&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;fadedlink&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;title=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Home&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ni&quot;&gt;&amp;amp;laquo;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt; CSS changes
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;small&amp;gt;&lt;/span&gt;28 Oct 2012&lt;span class=&quot;nt&quot;&gt;&amp;lt;/small&amp;gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;

  &lt;span class=&quot;nt&quot;&gt;&amp;lt;nav&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;ul&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;clearfix&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/categories/index.html#css&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;css&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;post&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;role=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;main&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Today I’ve been changing a bit the CSS that creates the layout of this site. Almost the whole style was defined by my pal &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.twitter.com/rafeca&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;@rafeca&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt; while creating &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.rafeca.com&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;his blog&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;. I have borrowed it :smile:.&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Although I am not an expert on CSS, I like hacking a bit of this :squirrel:.&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;I summarize the changes in the following sections.&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;h2&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;bottom-links-showing-a---character&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Bottom links showing a “-“ character&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;I think this is a common issue in a lot of sites: when you define a link containing an image, it may appear an annoying hyphen character on the right side of the image when the cursor is hover it. It’s been happening in this blog on the footer links.&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;To change this behavior, remove the &lt;span class=&quot;nt&quot;&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;img&lt;span class=&quot;nt&quot;&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt; element and define the image as background, ensuring the text inside the &lt;span class=&quot;nt&quot;&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;a&lt;span class=&quot;nt&quot;&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt; element is indented outside the screen, far away from the visible divs.&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;figure&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;highlight&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;pre&amp;gt;&amp;lt;code&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;language-html&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-lang=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;html&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;    &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nt&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ni&quot;&gt;&amp;amp;lt;&lt;/span&gt;footer&lt;span class=&quot;ni&quot;&gt;&amp;amp;gt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;c&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ni&quot;&gt;&amp;amp;lt;&lt;/span&gt;!-- Before --&lt;span class=&quot;ni&quot;&gt;&amp;amp;gt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nt&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ni&quot;&gt;&amp;amp;lt;&lt;/span&gt;a&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;na&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;class=&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;s&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&quot;fadedlink&quot;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;na&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;href=&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;s&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&quot;https://github.com/juandebravo&quot;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nt&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ni&quot;&gt;&amp;amp;gt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nt&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ni&quot;&gt;&amp;amp;lt;&lt;/span&gt;img&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;na&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;src=&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;s&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&quot;/gfx/github-logo.png&quot;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;na&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;alt=&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;s&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&quot;@github&quot;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nt&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ni&quot;&gt;&amp;amp;gt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nt&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ni&quot;&gt;&amp;amp;lt;&lt;/span&gt;/a&lt;span class=&quot;ni&quot;&gt;&amp;amp;gt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;c&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ni&quot;&gt;&amp;amp;lt;&lt;/span&gt;!-- Now --&lt;span class=&quot;ni&quot;&gt;&amp;amp;gt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nt&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ni&quot;&gt;&amp;amp;lt;&lt;/span&gt;a&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;na&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;class=&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;s&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&quot;fadedlink footer_link github&quot;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;na&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;href=&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;s&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&quot;https://github.com/juandebravo&quot;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nt&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ni&quot;&gt;&amp;amp;gt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
        @github
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nt&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ni&quot;&gt;&amp;amp;lt;&lt;/span&gt;/a&lt;span class=&quot;ni&quot;&gt;&amp;amp;gt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nt&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ni&quot;&gt;&amp;amp;lt;&lt;/span&gt;/footer&lt;span class=&quot;ni&quot;&gt;&amp;amp;gt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/figure&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;figure&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;highlight&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;pre&amp;gt;&amp;lt;code&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;language-css&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-lang=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;css&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nc&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;.footer_link&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;{&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nl&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;width&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;:&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;m&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;25px&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nl&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;display&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;:&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;n&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;inline-block&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nl&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;text-indent&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;:&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;m&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;-1000px&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nc&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;.github&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;{&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nl&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;background&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;:&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;sx&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;url(&quot;/gfx/github-logo.png&quot;)&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nb&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;no-repeat&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nb&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;scroll&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;m&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;0&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nb&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;transparent&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/figure&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;h2&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;increase-body-font-size&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Increase body font size&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This one is the easiest :sweat_smile:.&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;figure&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;highlight&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;pre&amp;gt;&amp;lt;code&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;language-css&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-lang=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;css&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nt&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;body&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;{&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nl&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;margin&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;:&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;m&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;0&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nl&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;line-height&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;:&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;m&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;1.4&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;c&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;/* Before */&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nl&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;font-size&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;:&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;m&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;16px&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;c&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;/* Now */&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nl&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;font-size&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;:&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;m&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;18px&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/figure&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;h2&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;list-style-type&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;List style type&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;In both the &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/index.html&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;main&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt; and the &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/open_source.html&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;open source&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt; pages, while defining &lt;span class=&quot;nt&quot;&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;li&lt;span class=&quot;nt&quot;&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt; elements the default circle character was being used. I’ve changed the CSS to support an Unicode code point using the &lt;span class=&quot;nt&quot;&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;:before&lt;span class=&quot;nt&quot;&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt; clause.&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;figure&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;highlight&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;pre&amp;gt;&amp;lt;code&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;language-css&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-lang=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;css&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nc&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;.container&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nt&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;ul&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nc&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;.posts&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;{&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;c&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;/* Do not use list decoration */&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nl&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;list-style&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;:&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nb&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;none&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nc&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;.container&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nt&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;ul&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nc&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;.posts&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nt&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;li&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nd&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;:before&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;{&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;c&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;/* Add a before content */&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nl&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;content&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;:&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;s1&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&quot;\0445&quot;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/figure&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;h2&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;predefined-width-on-the-left-side-while-indexing-stuff&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Predefined width on the left side while indexing stuff&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;The &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/index.html&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;main&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt; page shows a the list of posts titles and their posting date. The content was not aligned:&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Before:&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;li&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;post&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;list-style-type:none; padding-left: 30px&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&amp;gt;&lt;/span&gt;05 Aug 2012&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;title=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Ensuring Array as object type&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/2012/08/05/ensuring-array-as-object-type&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Ensuring Array as object type&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;li&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;post&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;list-style-type:none; padding-left: 30px&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&amp;gt;&lt;/span&gt;24 Jul 2012&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;title=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Things I like using python (part II)&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/2012/07/24/why-python-rocks_and_two&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Things I like using python (part II)&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;After:&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;li&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;post&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;list-style-type:none; padding-left: 30px&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;left_title&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;05 Aug 2012&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;title=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Ensuring Array as object type&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/2012/08/05/ensuring-array-as-object-type&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Ensuring Array as object type&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;li&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;post&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;list-style-type:none; padding-left: 30px&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;left_title&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;24 Jul 2012&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;title=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Things I like using python (part II)&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/2012/07/24/why-python-rocks_and_two&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Things I like using python (part II)&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;figure&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;highlight&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;pre&amp;gt;&amp;lt;code&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;language-css&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-lang=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;css&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nc&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;.left_title&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;{&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nl&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;display&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;:&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;n&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;inline-block&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nl&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;min-width&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;:&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;m&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;110px&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;/figure&amp;gt;&lt;/span&gt;



  &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;back&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ni&quot;&gt;&amp;amp;laquo;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Home&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;&amp;lt;!--h2&amp;gt;Related Posts&amp;lt;/h2&amp;gt;
&amp;lt;ul class=&quot;posts_list&quot;&amp;gt;
  
    &amp;lt;li class=&quot;post&quot;&amp;gt;
  &amp;lt;a href=&quot;/2025/04/12/configure-mcp-server-with-asdf/&quot; title=&quot;Configure MCP server with asdf for Node.js&quot;&amp;gt;Configure MCP server with asdf for Node.js&amp;lt;/a&amp;gt;
  &amp;lt;span class=&quot;date&quot;&amp;gt;(12 Apr 2025)&amp;lt;/span&amp;gt;
&amp;lt;/li&amp;gt;

  
    &amp;lt;li class=&quot;post&quot;&amp;gt;
  &amp;lt;a href=&quot;/2023/03/27/get-pull-requests-metrics-with-chat-gpt/&quot; title=&quot;Get Pull Request metrics with chat-gpt&quot;&amp;gt;Get Pull Request metrics with chat-gpt&amp;lt;/a&amp;gt;
  &amp;lt;span class=&quot;date&quot;&amp;gt;(27 Mar 2023)&amp;lt;/span&amp;gt;
&amp;lt;/li&amp;gt;

  
    &amp;lt;li class=&quot;post&quot;&amp;gt;
  &amp;lt;a href=&quot;/2023/03/26/mount-external-volume-write-permissions/&quot; title=&quot;How to mount an external volume with write permissions&quot;&amp;gt;How to mount an external volume with write permissions&amp;lt;/a&amp;gt;
  &amp;lt;span class=&quot;date&quot;&amp;gt;(26 Mar 2023)&amp;lt;/span&amp;gt;
&amp;lt;/li&amp;gt;

  
&amp;lt;/ul--&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;hr&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Comments&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;disqus_thread&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text/javascript&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;cm&quot;&gt;/* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;disqus_shortname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;juandebravo&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// required: replace example with your forum shortname&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;//var disqus_developer = 1; // developer mode is on, for testing locally&lt;/span&gt;

  &lt;span class=&quot;cm&quot;&gt;/* * * DON&apos;T EDIT BELOW THIS LINE * * */&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dsq&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dsq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;text/javascript&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dsq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;dsq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;src&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;https://&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;disqus_shortname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;.disqus.com/embed.js&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dsq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;})();&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;noscript&amp;gt;&lt;/span&gt;Please enable JavaScript to view the &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://disqus.com/?ref_noscript&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;comments powered by
    Disqus.&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/noscript&amp;gt;&lt;/span&gt;

  
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;back&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;ni&quot;&gt;&amp;amp;laquo;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Home&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;8-write-an-emoji-in-a-markdown-file-and-run-the-server&quot;&gt;8. Write an emoji in a markdown file and run the server&lt;/h2&gt;

&lt;p&gt;For instance to include a smile, write &lt;strong&gt;:smile:&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;9-run-jekyll&quot;&gt;9. Run jekyll&lt;/h2&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;jekyll &lt;span class=&quot;nt&quot;&gt;--server&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--auto&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;10-enjoy&quot;&gt;10. Enjoy&lt;/h2&gt;

&lt;p&gt;:neckbeard: :squirrel: :bug: :monkey: :scream: :hankey: :smile:&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>CSS changes</title>
   <link href="http://juandebravo.com/2012/10/28/css-changes/"/>
   <updated>2012-10-28T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2012/10/28/css-changes/</id>
   <content type="html">&lt;p&gt;Today I’ve been changing a bit the CSS that creates the layout of this site. Almost the whole style was defined by my pal &lt;a href=&quot;http://www.twitter.com/rafeca&quot;&gt;@rafeca&lt;/a&gt; while creating &lt;a href=&quot;http://www.rafeca.com&quot;&gt;his blog&lt;/a&gt;. I have borrowed it :smile:.&lt;/p&gt;

&lt;p&gt;Although I am not an expert on CSS, I like hacking a bit of this :squirrel:.&lt;/p&gt;

&lt;p&gt;I summarize the changes in the following sections.&lt;/p&gt;

&lt;h2 id=&quot;bottom-links-showing-a---character&quot;&gt;Bottom links showing a “-“ character&lt;/h2&gt;

&lt;p&gt;I think this is a common issue in a lot of sites: when you define a link containing an image, it may appear an annoying hyphen character on the right side of the image when the cursor is hover it. It’s been happening in this blog on the footer links.&lt;/p&gt;

&lt;p&gt;To change this behavior, remove the &lt;strong&gt;img&lt;/strong&gt; element and define the image as background, ensuring the text inside the &lt;strong&gt;a&lt;/strong&gt; element is indented outside the screen, far away from the visible divs.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;    &lt;span class=&quot;nt&quot;&gt;&amp;lt;footer&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Before --&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;fadedlink&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://github.com/juandebravo&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/gfx/github-logo.png&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;alt=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;@github&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Now --&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;fadedlink footer_link github&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://github.com/juandebravo&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        @github
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/footer&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.footer_link&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;25px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inline-block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;text-indent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;-1000px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;.github&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;url(&quot;/gfx/github-logo.png&quot;)&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;no-repeat&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;scroll&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;transparent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;increase-body-font-size&quot;&gt;Increase body font size&lt;/h2&gt;
&lt;p&gt;This one is the easiest :sweat_smile:.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;line-height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1.4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;/* Before */&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;16px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;/* Now */&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;18px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;list-style-type&quot;&gt;List style type&lt;/h2&gt;

&lt;p&gt;In both the &lt;a href=&quot;/index.html&quot;&gt;main&lt;/a&gt; and the &lt;a href=&quot;/open_source.html&quot;&gt;open source&lt;/a&gt; pages, while defining &lt;strong&gt;li&lt;/strong&gt; elements the default circle character was being used. I’ve changed the CSS to support an Unicode code point using the &lt;strong&gt;:before&lt;/strong&gt; clause.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.container&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;ul&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;.posts&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;c&quot;&gt;/* Do not use list decoration */&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;list-style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;.container&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;ul&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;.posts&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:before&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;c&quot;&gt;/* Add a before content */&lt;/span&gt;
	&lt;span class=&quot;nl&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&quot;\0445&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;predefined-width-on-the-left-side-while-indexing-stuff&quot;&gt;Predefined width on the left side while indexing stuff&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;/index.html&quot;&gt;main&lt;/a&gt; page shows a the list of posts titles and their posting date. The content was not aligned:&lt;/p&gt;

&lt;p&gt;Before:&lt;/p&gt;

&lt;li class=&quot;post&quot; style=&quot;list-style-type:none; padding-left: 30px&quot;&gt;
  &lt;span&gt;05 Aug 2012&lt;/span&gt;
  &lt;a title=&quot;Ensuring Array as object type&quot; href=&quot;/2012/08/05/ensuring-array-as-object-type&quot;&gt;Ensuring Array as object type&lt;/a&gt;
&lt;/li&gt;
&lt;li class=&quot;post&quot; style=&quot;list-style-type:none; padding-left: 30px&quot;&gt;
  &lt;span&gt;24 Jul 2012&lt;/span&gt;
  &lt;a title=&quot;Things I like using python (part II)&quot; href=&quot;/2012/07/24/why-python-rocks_and_two&quot;&gt;Things I like using python (part II)&lt;/a&gt;
&lt;/li&gt;

&lt;p&gt;After:&lt;/p&gt;
&lt;li class=&quot;post&quot; style=&quot;list-style-type:none; padding-left: 30px&quot;&gt;
  &lt;span class=&quot;left_title&quot;&gt;05 Aug 2012&lt;/span&gt;
  &lt;a title=&quot;Ensuring Array as object type&quot; href=&quot;/2012/08/05/ensuring-array-as-object-type&quot;&gt;Ensuring Array as object type&lt;/a&gt;
&lt;/li&gt;
&lt;li class=&quot;post&quot; style=&quot;list-style-type:none; padding-left: 30px&quot;&gt;
  &lt;span class=&quot;left_title&quot;&gt;24 Jul 2012&lt;/span&gt;
  &lt;a title=&quot;Things I like using python (part II)&quot; href=&quot;/2012/07/24/why-python-rocks_and_two&quot;&gt;Things I like using python (part II)&lt;/a&gt;
&lt;/li&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.left_title&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inline-block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;min-width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;110px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</content>
 </entry>
 
 <entry>
   <title>How to paste code in keynote</title>
   <link href="http://juandebravo.com/2012/10/21/how-to-paste-code-in-keynote/"/>
   <updated>2012-10-21T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2012/10/21/how-to-paste-code-in-keynote/</id>
   <content type="html">&lt;p&gt;I use &lt;strong&gt;Twitter favourites&lt;/strong&gt; feature to mark as &lt;strong&gt;read it later&lt;/strong&gt; tweets that contain a link that seems interesting. 
Eventually I tidy up my long list of unread interesting stuff and today I found out about the following item.&lt;/p&gt;

&lt;p&gt;There was &lt;a href=&quot;https://twitter.com/spastorino/status/250708430036295681&quot;&gt;this tweet&lt;/a&gt; from &lt;a href=&quot;https://twitter.com/spastorino/&quot;&gt;Santiago Pastorino&lt;/a&gt; about how to include highlighted code into a Keynote.app presentation:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Copy the text to the pasteboard from your editor&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# &amp;lt;language&amp;gt; should be a programming language supported by pygmentize.&lt;/span&gt;

pbpaste | pygmentize &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; &amp;lt;language&amp;gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; rtf | pbcopy

&lt;span class=&quot;c&quot;&gt;# Paste the pasteboard content into Keynote.app&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;As simple as that. Keynote.app recognizes automatically the RTF format and therefore the code is highlighted as defined by pygmentize. Awesome tip!&lt;/p&gt;

&lt;p&gt;Two last comments:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;if you try to do this using &lt;strong&gt;Microsoft PowerPoint&lt;/strong&gt; for OS X, remember to choose “Special paste”. PowerPoint does not recognize automatically the RTF format, which by the way was developed by Microsoft. Great engineering work (the &lt;a href=&quot;RTF definition&quot;&gt;http://en.wikipedia.org/wiki/Rich_Text_Format&lt;/a&gt; with a really poor user experience (“special paste” sucks).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;if you are creating a code oriented lecture, my recommendation is you give a try to &lt;a href=&quot;https://github.com/fxn/tkn&quot;&gt;Terminal Keynote&lt;/a&gt;. I’ve used it once with great results.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>First steps with Scala</title>
   <link href="http://juandebravo.com/2012/09/26/first-steps-with-scala/"/>
   <updated>2012-09-26T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2012/09/26/first-steps-with-scala/</id>
   <content type="html">&lt;p&gt;Last week I started a &lt;a href=&quot;https://www.coursera.org&quot;&gt;Coursera&lt;/a&gt; online training course about Functional programming using Scala. The course is leaded by &lt;a href=&quot;http://en.wikipedia.org/wiki/Martin_Odersky&quot;&gt;Martin Odersky&lt;/a&gt;, the creator of Scala language program, so it’s a great chance to improve my little knowledge of funcional programming in general and Scala in particular.&lt;/p&gt;

&lt;p&gt;When you start working with a new language, first thing you should do is find out the right tools that will make you feel comfortable while spending several hours learning and writing code.&lt;/p&gt;

&lt;p&gt;I’ll summarize the steps I followed on my computer (running Mac OS X).&lt;/p&gt;

&lt;h1 id=&quot;1-install-the-interpreter&quot;&gt;1. Install the interpreter&lt;/h1&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;scala&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;2-install-sbt-the-build-tool&quot;&gt;2. Install SBT, the build tool&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/harrah/xsbt/wiki&quot;&gt;SBT&lt;/a&gt; is for Scala what Maven is for Java. I haven’t used it in depth yet, but hopefully it’ll suck less than Maven.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;sbt&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;3-write-your-first-scala-code-using-the-scala-repl&quot;&gt;3. Write your first Scala code using the Scala REPL&lt;/h1&gt;
&lt;p&gt;Scala provides a built-in interpreter (Read-Evaluate-Print Loop) to write and run Scala code very easily.&lt;/p&gt;

&lt;p&gt;You can run the Scala &lt;strong&gt;REPL&lt;/strong&gt; either using sbt or &lt;strong&gt;scala&lt;/strong&gt; command:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Using SBT&lt;/span&gt;
juandebravo &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;~/bin] λ sbt console
scala&amp;gt;
scala&amp;gt; println&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Hello world&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
Hello world
&lt;span class=&quot;c&quot;&gt;# Using scala&lt;/span&gt;
juandebravo &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;~/bin] λ scala
scala&amp;gt;
scala&amp;gt; println&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Hello world&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
Hello world&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;4-configure-your-ide-of-choice-sublime-text-2&quot;&gt;4. Configure your IDE of choice. Sublime Text 2&lt;/h1&gt;
&lt;p&gt;My coworker &lt;a href=&quot;http://www.tonicebrian.com&quot;&gt;Toni Cebrian&lt;/a&gt; wrote a &lt;a href=&quot;http://www.tonicebrian.com/2011/05/16/comparison-of-ides-for-scala-development/&quot;&gt;post comparing IDEs&lt;/a&gt; to write Scala code. I’ll not repeat his text but write a bit about my personal choice: &lt;a href=&quot;http://www.sublimetext.com/2&quot;&gt;SublimeText2&lt;/a&gt;. I started using Sublime Text 2 one year and a half ago coding ruby, I stayed on that when I switched to python, and I’ll give it a try for Scala too. I starred some time ago &lt;a href=&quot;https://twitter.com/alexey_r/status/185839109049303044&quot;&gt;this tweet&lt;/a&gt; about &lt;a href=&quot;http://blog.hugeaim.com/2012/03/22/use-sublime-text-2-for-scala-development/&quot;&gt;how to use Sublime Text 2 for Scala development&lt;/a&gt;, and eventually I read it :-)&lt;/p&gt;

&lt;p&gt;It seems that the best option is to install the plugin &lt;a href=&quot;https://github.com/sublimescala/sublime-ensime&quot;&gt;sublime-ensime&lt;/a&gt;. It was a good surprise to find out that my pal &lt;a href=&quot;http://www.twitter.com/casualjim&quot;&gt;@casualjim&lt;/a&gt; is the original author of this plugin. &lt;a href=&quot;https://github.com/sublimescala/sublime-ensime&quot;&gt;Sublime-ensime&lt;/a&gt; is a plugin that provides integration between Scala and &lt;a href=&quot;http://aemoncannon.github.com/ensime/index.html&quot;&gt;ENSIME&lt;/a&gt;, the ENhanced Scala Interaction Mode for Emacs.
Follow the instructions in the &lt;a href=&quot;https://github.com/sublimescala/sublime-ensime&quot;&gt;sublime-ensime github main page&lt;/a&gt; to make it work.&lt;/p&gt;

&lt;p&gt;Some months ago I created project showing some cool Scala features, check it out in my &lt;a href=&quot;https://github.com/juandebravo/scala-examples&quot;&gt;github repository&lt;/a&gt;. To run it using Sublime Text 2, create a new Build system with the following configuration:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;sbt&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
	&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;source.scala&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;working_dir&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;${project_path}&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</content>
 </entry>
 
 <entry>
   <title>Dynamic loading</title>
   <link href="http://juandebravo.com/2012/09/16/dynamic-loading/"/>
   <updated>2012-09-16T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2012/09/16/dynamic-loading/</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;/gfx/posts/dynamic-loading/most-interesing-man.png&quot; alt=&quot;Dynamic loading&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In the project I am working right now, we are reusing a Django project to develop two different products, productA and productB :-). These products frequently require the same service layer and the code can be directly reused, but in some scenarios different code is required.&lt;/p&gt;

&lt;p&gt;Django project reusage gives us some advantages. Here I highlight some of them:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;authentication&lt;/li&gt;
  &lt;li&gt;authorization&lt;/li&gt;
  &lt;li&gt;logging&lt;/li&gt;
  &lt;li&gt;URL routes&lt;/li&gt;
  &lt;li&gt;testing strategy&lt;/li&gt;
  &lt;li&gt;security tests&lt;/li&gt;
  &lt;li&gt;third party integrations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our current solution to run different logic in both products, instead of using project configuration, is &lt;strong&gt;dynamic loading&lt;/strong&gt;. To implement it, we have defined our own code structure respecting Django default structure:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;- django_project_root
  - django_app_1
    - __init__.py
    - services.py
    - projectA
       - __init__.py
       - services.py
    - projectB
       - __init__.py
       - sevices.py
  - django_app_2
    - __init__.py
    - services.py
    - projectB
      - __init__.py
      - services.py&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If the Django application is running as projectA, the service logic being used is:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;for django_app_1 application, the module django_app_1.projectA.services&lt;/li&gt;
  &lt;li&gt;for django_app_2 application, the module django_app_2.services (as django_app_2.projectA.services module is not created).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ProjectB has defined specific logic in both Django applications, and therefore no generic one is used.&lt;/p&gt;

&lt;p&gt;Find underneath the snippet of code (simplified) we’re using to know which module must be loaded:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;application_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;module_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;application_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;.&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;project&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;.&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;module&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;__import__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;module_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ImportError&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;warn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Unable to import module: {0} -&amp;gt; {1}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;module_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;__import__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;application_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;.&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Example
&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;get_module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;django_app_1&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;projectA&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;services&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Pretty simple. I’m trying to load a module, and if it fails, I’m logging a warning.
Sometimes the warning is the expected behavior (i.e. projectA does not define its own django_app_2 service logic), but it could also happen that an exception is raised while parsing a module code, and therefore the module cannot be imported (i.e. projectB django_app_2 service logic has a syntax error). Not logging this situation will hide possible undesired errors.&lt;/p&gt;

&lt;p&gt;This is something that Django is not doing (at least in version 1.3.1) and caused me some paintful last Friday. This command:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;python&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;manage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;py&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;collectstatic&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;projectA_settings&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;generated the following result:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;Unknown&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;collectstatic&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;WTF! I was getting crazy as I was pretty sure the &lt;em&gt;django.contrib.staticfiles&lt;/em&gt; app was installed in the projectA settings file. After some debugging I came out with the problem: Django is using dynamic loading, I had a missing dependency in a model module, and the projectA settings wasn’t been loaded, therefore collectstatic was not a valid command.&lt;/p&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;To sum up, be careful while dynamic loading your code and log any possible error that may raise during the process. I do, you and &lt;a href=&quot;https://github.com/django/django/blob/master/django/utils/importlib.py&quot;&gt;Django&lt;/a&gt; should too. Otherwise, weird errors will happen because the root of the problem is being hidden.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Baruco, First day</title>
   <link href="http://juandebravo.com/2012/09/08/baruco-saturday/"/>
   <updated>2012-09-08T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2012/09/08/baruco-saturday/</id>
   <content type="html">&lt;h1 id=&quot;introduction&quot;&gt;Introduction&lt;/h1&gt;

&lt;p&gt;This weekend &lt;a href=&quot;http://obrasocial.lacaixa.es/nuestroscentros/cosmocaixabarcelona/cosmocaixabarcelona_es.html&quot;&gt;CosmoCaixa building&lt;/a&gt;, in Barcelona, is hosting the &lt;a href=&quot;http://www.baruco.org&quot;&gt;BArcelona RUby COnference&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So I’ll summarize the weekend talks, let you know about the awesome speakers, the wonderful venue and the great organization.&lt;/p&gt;

&lt;h1 id=&quot;keynote-by-scott-chacon-back-to-first-principles&quot;&gt;Keynote by Scott Chacon. Back to First Principles&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;http://twitter.com/chacon&quot;&gt;Scott Chacon&lt;/a&gt;, &lt;a href=&quot;https://www.github.com&quot;&gt;github&lt;/a&gt; cofunder, was the first speaker on stage. He talked us through how he sees the future of working for a software company or at least how he’d like it to be:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;No timetable&lt;/strong&gt;: stop working 8 to 17, start acting as an artist that needs inspiration and work in creative moments.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;No vacations&lt;/strong&gt;: consider that anyone should know when can go on holidays, no rules on that. (I do know that this is something already in place in some companies such as &lt;a href=&quot;http://mashable.com/2012/04/13/netflix-unlimited-vacation/&quot;&gt;Netflix&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;No expenses sheets&lt;/strong&gt;: give people the freedom to know what/when/how much he may spend.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;No managers&lt;/strong&gt;: consider when or why you need a manager. In those situations, could he be replaced by a software program? :)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All the above defines the way an open source project works nowdays.&lt;/p&gt;

&lt;p&gt;Some examples of companies that are questioning the usual way to work:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.valvesoftware.com/company/people.html&quot;&gt;valve&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.gore.com/en_xx/aboutus/culture/index.html&quot;&gt;gore&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://github.com&quot;&gt;github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;rubymotion&quot;&gt;RubyMotion&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;http://www.rubymotion.com/&quot;&gt;RubyMotion&lt;/a&gt; is a commercial product (162,61 € a licence, coming soon a free licence alternative) that enables a way to create iOS applications using Ruby language.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good points&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Reuse your Ruby knowledge instead of learning a new language, new patterns, etc.&lt;/li&gt;
  &lt;li&gt;Use the expressiveness of Ruby instead of Objective-C syntax&lt;/li&gt;
  &lt;li&gt;Get rid of XCode and use your IDE/text editor of choice&lt;/li&gt;
  &lt;li&gt;Community&lt;/li&gt;
  &lt;li&gt;Commandline: you can use your commandline to build the project&lt;/li&gt;
  &lt;li&gt;Storyboards&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/CocoaPods/Specs&quot;&gt;Cocoapods&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How to create the simplest RubyMotion application:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;motion create sample
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;sample
rake&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Speakers pointed out that ARC (Automatic Reference Counter) it’s the gear that enables RubyMotion (so you need at least iOS 5). Underneath, RubyMotion uses a MacRuby.&lt;/p&gt;

&lt;p&gt;To them it should not be used for production right now, perhaps in six months time.&lt;/p&gt;

&lt;p&gt;My personal opinion, you should learn more than one programming language and at least try the native Objective-C language, create your own opinion about if you should use RubyMotion or any other high level framework such as &lt;a href=&quot;http://phonegap.com/&quot;&gt;PhoneGap&lt;/a&gt; or &lt;a href=&quot;http://www.appcelerator.com/&quot;&gt;Titanium&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;getting-consistent-behavior-across-your-api&quot;&gt;Getting consistent behavior across your API&lt;/h1&gt;

&lt;p&gt;Principles for either internal or external API:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Less Surprise principle&lt;/li&gt;
  &lt;li&gt;Consistent formatting&lt;/li&gt;
  &lt;li&gt;Consistent naming and format in the overall API&lt;/li&gt;
  &lt;li&gt;Handle carefully unexpected responses&lt;/li&gt;
  &lt;li&gt;Ensure you are not creating bad or missing error messages&lt;/li&gt;
  &lt;li&gt;Let people know what you accept and give them examples&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How to achieve:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Centralize behavior&lt;/li&gt;
  &lt;li&gt;DRY (dont repeat yourself)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Warm up:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Treat you API like the interface it is&lt;/li&gt;
  &lt;li&gt;Aim for consitency&lt;/li&gt;
  &lt;li&gt;Become your own client and challenge your API design&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;deconstructing-the-framework&quot;&gt;Deconstructing the framework&lt;/h1&gt;
&lt;p&gt;Gary Bernhardt talked about how useful is the SRP (Single Responsability Principle) while creating a well-defined application that should be maintained during a long period. I do agree.
Regarding this principle, he mentioned Rails controller as a piece of software that, by default, is in charge of different tasks: authorization, authentication, service logic, form validation, serialization.
He has been working on that OS project called &lt;a href=&quot;https://github.com/garybernhardt/raptor&quot;&gt;raptor&lt;/a&gt; that is a proof of concept, not ready to use in production, about how to split code and separate reponsabilities in a Rails application.&lt;/p&gt;

&lt;h1 id=&quot;life-beyond-http&quot;&gt;Life beyond HTTP&lt;/h1&gt;
&lt;p&gt;Consider a protocol as a tool you can use to improve your system. About application protocols:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;SMTP&lt;/strong&gt; (Simple Mail Transfer Protocol)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;DNS&lt;/strong&gt; (Domain Name System)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;XMPP&lt;/strong&gt; (Extensible Messaging and Presence Protocol)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;IRC&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SSH&lt;/strong&gt; (Secure Shell)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;STOMP&lt;/strong&gt; (Streaming Text Oriented Messaging Protocol)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SPDY&lt;/strong&gt; (): Multiplexed HTTP:
    &lt;ul&gt;
      &lt;li&gt;open an HTTP connection and can send several requests in parallel.&lt;/li&gt;
      &lt;li&gt;request priorization&lt;/li&gt;
      &lt;li&gt;compressed headers&lt;/li&gt;
      &lt;li&gt;server pushed streams&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;why-agile&quot;&gt;Why Agile&lt;/h1&gt;

&lt;p&gt;Software engineering has failed during the past decades while trying to achieve:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Reduce code&lt;/li&gt;
  &lt;li&gt;Eliminate human errors&lt;/li&gt;
  &lt;li&gt;Eliminate project variability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;http://www.twitter.com/nusco&quot;&gt;Paolo&lt;/a&gt; suggests using the scientific method when developing software:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;observation&lt;/li&gt;
  &lt;li&gt;hypothesis&lt;/li&gt;
  &lt;li&gt;experiment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Something that has become lately to the news as part of the &lt;a href=&quot;http://en.wikipedia.org/wiki/Lean_Startup&quot;&gt;Lean Startup&lt;/a&gt; approach.&lt;/p&gt;

&lt;h1 id=&quot;lighting-talks&quot;&gt;Lighting talks&lt;/h1&gt;

&lt;p&gt;Last, but not least, there has been ten lightings talks (5’ each) about different stuff like graph databases and the new service by &lt;a href=&quot;http://www.aentos.com/en&quot;&gt;aentos&lt;/a&gt; called &lt;a href=&quot;http://graphendb.com&quot;&gt;GrapheneDB&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;warm-up&quot;&gt;Warm up&lt;/h1&gt;
&lt;p&gt;Great speakers (Scott Chacon, Anthony Eden, Paolo Perrotta), great contents (API uniformity, Deconstructing the framework), cool people, and two new t-shirts for my ever growing collection.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ensuring Array as object type</title>
   <link href="http://juandebravo.com/2012/08/05/ensuring-array-as-object-type/"/>
   <updated>2012-08-05T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2012/08/05/ensuring-array-as-object-type/</id>
   <content type="html">&lt;p&gt;It happens often that you need an array as object type, and even if you have defined your API like that, you still want to double check that the parameter received in your method is an array:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;param&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;is_a?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# Service logic here&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Fortunalety in ruby you have the following feature that converts your parameter to an array, or does nothing in case it is already an array:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;param&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This feature does not exist in python, or I haven’t found it though.&lt;/p&gt;

&lt;p&gt;The following snippet covers that funcionality:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# list_utils.py
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;list_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;more_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    Creates a list using one or more elements.
    If the parameter is a list, do nothing
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;isinstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;values&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;more_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;more_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;list_utils&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list_&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;send_mail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;destinations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;destinations&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;destinations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destination&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# your service logic&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You can check the behavior with the following chunk of unit tests:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;unittest&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;list_utils&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list_&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ListTests&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unittest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TestCase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_parameter_is_a_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;list_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;foo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;foo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_parameter_is_an_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;list_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;foo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;foo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_parameter_is_an_integer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;list_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_parameter_is_a_list_with_multiple_elements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;list_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_parameter_is_multiple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;list_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_parameter_is_none&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;list_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;__main__&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;unittest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
</content>
 </entry>
 
 <entry>
   <title>Things I like using python (part II)</title>
   <link href="http://juandebravo.com/2012/07/24/why-python-rocks_and_two/"/>
   <updated>2012-07-24T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2012/07/24/why-python-rocks_and_two/</id>
   <content type="html">&lt;h1 id=&quot;introduction&quot;&gt;Introduction&lt;/h1&gt;

&lt;p&gt;Here it goes my second and last post on the “things that I like about coding in python” series in which was missing a small section on how cool these features (below) are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Decorators&lt;/li&gt;
  &lt;li&gt;Context managers&lt;/li&gt;
  &lt;li&gt;Use blank spaces to define code blocks&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;decorators&quot;&gt;Decorators&lt;/h1&gt;
&lt;p&gt;A decorator is a function that takes at least an argument, a function object, and returns a single value, a function object. It’s commonly used to, taking advantage of python closures support, add new features to the original function object (the one received as argument).&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.python.org/dev/peps/pep-0318/&quot;&gt;Decorators were defined in PEP 318&lt;/a&gt; as a way to ease the definition of class and static methods.&lt;/p&gt;

&lt;p&gt;Before decorators reached python, the following excerpt was needed to create a class/static method:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Hello {0} from my class method&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bazz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Hello {0} from my static method&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# Convert bar from instance to class method
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;classmethod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# Create a static method
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;bazz&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;staticmethod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bazz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;__main__&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;John Doe&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bazz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;John Doe&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Reminder: the main difference between static and class methods is that a class method can be overriden by a child, which is not true for a static method. Also a class method needs the class object as first parameter in the method definition. At this point, I don’t find a good reason to define a static method though.&lt;/p&gt;

&lt;p&gt;Using decorators and its syntax sugar (the &lt;strong&gt;@&lt;/strong&gt; symbol), the previous excerpt can be re-written to:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# Define bar as a class method
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# As first parameter we could use &apos;self&apos;, but the facto standard is to use &apos;cls&apos; while
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# defining class methods
&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;classmethod&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Hello {0} from my class method&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Define bazz as a static method
&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;staticmethod&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bazz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Hello {0} from my static method&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;__main__&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;John Doe&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bazz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;John Doe&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The best blog post explaining decorators I’ve found so far is &lt;a href=&quot;http://pythonconquerstheuniverse.wordpress.com/2012/04/29/python-decorators&quot;&gt;this one from Steve Ferg&lt;/a&gt;. I find decorators quite useful when you need transversal functionalities in your code. A set of examples can be found in &lt;a href=&quot;http://wiki.python.org/moin/PythonDecoratorLibrary&quot;&gt;wiki.python.org&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;example&quot;&gt;Example&lt;/h3&gt;

&lt;p&gt;The following code creates a decorator that dumps the arguments that a function/method receives when executed. The base of that code is taken from &lt;a href=&quot;http://wiki.python.org/moin/PythonDecoratorLibrary#Easy_Dump_of_Function_Arguments&quot;&gt;wiki.python.org#Easy_Dump_Of_Function_Arguments&lt;/a&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# decorator_utils.py
&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;logging&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;basicConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DEBUG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;dump_args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# get function arguments name
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;argnames&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;func_code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_varnames&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;func_code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_argcount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# get function name
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;fname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;func_name&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;echo_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
        Log arguments, including name, type and value
        &quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;format_arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;%s=%s&amp;lt;%s&amp;gt;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__class__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot; args =&amp;gt; {0}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;, &apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;format_arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argnames&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())))&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;echo_func&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# example.py
&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;decorator_utils&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dump_args&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UserModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    User model object
    &quot;&quot;&quot;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;

    &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;classmethod&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dump_args&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;find_by_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;

    &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dump_args&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__str__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;unicode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;utf-8&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__unicode__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dump_args&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;f1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;__main__&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;UserModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find_by_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;foo&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UserModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;879234-32423423&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;John&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;surname&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Doe&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;f1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;f1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;bazz&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The execution of the previous code generates the following output:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;λ python example.py

DEBUG:find_by_id: args &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cls&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt; &apos;__main__.UserModel&apos;&amp;gt;&amp;gt;, user_id=str&amp;lt;foo&amp;gt;
DEBUG:update: args =&amp;gt; self=UserModel&amp;lt;879234-32423423&amp;gt;, surname=str&amp;lt;Doe&amp;gt;, name=str&amp;lt;John&amp;gt;
DEBUG:f1: args =&amp;gt; user_id=UserModel&amp;lt;879234-32423423&amp;gt;, arg1=int&amp;lt;2&amp;gt;, arg2=int&amp;lt;3&amp;gt;
DEBUG:f1: args =&amp;gt; user_id=UserModel&amp;lt;879234-32423423&amp;gt;, arg1=int&amp;lt;2&amp;gt;, arg2=int&amp;lt;3&amp;gt;, foo=str&amp;lt;bazz&amp;gt;, bar=int&amp;lt;23&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;As it’s shown above (method &lt;em&gt;find_by_id&lt;/em&gt;), you can use more than one decorator in a function/method (and are executed bottom-up).&lt;/p&gt;

&lt;h1 id=&quot;context-managers-with-statement&quot;&gt;Context managers (&lt;strong&gt;with&lt;/strong&gt; statement)&lt;/h1&gt;

&lt;p&gt;A context manager allows you to create and manage a run time context. It is created when starting a &lt;strong&gt;with&lt;/strong&gt; statement, it’s available during the code execution inside the &lt;em&gt;with&lt;/em&gt; block, and is exited at the end of the &lt;em&gt;with&lt;/em&gt; code. The most commonly used scenario is while &lt;strong&gt;allocating resources&lt;/strong&gt;: a context manager ensures you use the resource only while it’s actually required and deallocates it when it should not be used anymore (of course python needs you to write the code properly for that if you are defining your own context manager).&lt;/p&gt;

&lt;p&gt;The basic example using python native library to handle a file object:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;/var/log/events.log&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;w&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;New user created&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The file &lt;em&gt;/var/log/events.log&lt;/em&gt; is opened when entering into the context manager, and closed when the code block is finished. You don’t need to catch exceptions, close the file, etc.&lt;/p&gt;

&lt;p&gt;To create a context manager you need to define a class that implements two methods, &lt;strong&gt;__enter__&lt;/strong&gt; and &lt;strong&gt;__exit__&lt;/strong&gt;. In the following code I’m creating a context manager, &lt;em&gt;user&lt;/em&gt;, that retrieves an object from an external source and stores it back if updated:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    Database object
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;has_changed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# logic to check if any user property has been updated
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    Context manager for a User object
    &quot;&quot;&quot;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__enter__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
        This code block is executed while entering a context manager
        &quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# mock that returns always a basic User
&lt;/span&gt;        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;John&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;surname&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Doe&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__exit__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
        This code block is executed at context manager exit
        &quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;has_changed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# here the save logic
&lt;/span&gt;            &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;__main__&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;00000-11111&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;name&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;Johnny&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Switching to ruby, something similar can be achieved with the following snippet:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Hash&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;attr_reader&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:user_id&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;params&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@user_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;block_given?&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;has_changed?&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# here the save logic&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;has_changed?&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# logic to check if any user property has been updated&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;True&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;find!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# mock that returns always a basic User instance&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;block_given?&lt;/span&gt;
        &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:&quot;John&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;surname&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:&quot;Doe&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Proc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
        &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:&quot;John&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;surname&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:&quot;Doe&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;0000-1111&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Johnny&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;use-blank-spaces-to-define-code-blocks&quot;&gt;Use blank spaces to define code blocks&lt;/h1&gt;
&lt;p&gt;Not too much to say about this. I thinks it increases readability.&lt;/p&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;I hope you’ve found these articles interesting. I’m sure some good points, like functions being first-class citizens or the collections and functools modules, are missing but at this point I just wanted to highlight my five coolest features. Let me know which are yours so my top five list could easily be “re-prioritized” :-)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Things I like using python (part I)</title>
   <link href="http://juandebravo.com/2012/07/16/why-python-rocks/"/>
   <updated>2012-07-16T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2012/07/16/why-python-rocks/</id>
   <content type="html">&lt;h1 id=&quot;introduction&quot;&gt;Introduction&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;/2012/05/31/yet-another-blog-in-the-world/&quot;&gt;As you know&lt;/a&gt; these lasts months I’ve spent quite some time coding python, the language chosen for the project to which I’ve devoted heart, soul and most of my weekends too…&lt;/p&gt;

&lt;p&gt;During the first weeks I really struggled to get the code alive as during the previous two years it was all bout ruby, so python has taken me out of my comfort zone which really hit me. Although I cannot call myself a python expert (yet), I’m enjoying this new friendship.&lt;/p&gt;

&lt;h1 id=&quot;things-i-like-using-python&quot;&gt;Things I like using python&lt;/h1&gt;

&lt;p&gt;I’m going to share some of my favourites features and I’d like to know yours, yours thoughts about them and any missed bit that may be key:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;List comprehensions&lt;/li&gt;
  &lt;li&gt;Generators&lt;/li&gt;
  &lt;li&gt;Decorators&lt;/li&gt;
  &lt;li&gt;Use blank spaces to define code blocks&lt;/li&gt;
  &lt;li&gt;Context managers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Find below a brief description and example about the first two dots.&lt;/p&gt;

&lt;h1 id=&quot;list-comprehensions&quot;&gt;List comprehensions&lt;/h1&gt;

&lt;p&gt;As python doc says, &lt;a href=&quot;http://docs.python.org/tutorial/datastructures.html#list-comprehensions&quot;&gt;“list comprehensions provide a concise way to create lists”&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;example&quot;&gt;Example&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;users&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;name&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;John Doe&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;email&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;john@doe.com&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
		 &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;name&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;Mike Cunhingam&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;email&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;mike@cunhingam.com&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Retrieve users email
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;emails&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;email&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Of course something similar can be done in ruby, but after some weeks I felt comfortable with the idea of iterate over objects in an array without calling a specific object method:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;users&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;name: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;John Doe&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;email: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;john@doe.com&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
		 &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;name: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;Mike Cunhingam&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;email: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;mike@cunhingam.com&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Retrieve users email&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;emails&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;List comprehensions can be used with any iterable object, as strings and arrays instances.&lt;/p&gt;

&lt;h1 id=&quot;generators&quot;&gt;Generators&lt;/h1&gt;

&lt;p&gt;Again reading through python docs, &lt;a href=&quot;http://docs.python.org/tutorial/classes.html#generators&quot;&gt;“generators are a simple and powerful tool for creating iterators”&lt;/a&gt;, covered in &lt;a href=&quot;http://www.python.org/dev/peps/pep-0255/&quot;&gt;PEP255&lt;/a&gt;. Generators may be used when you need to maintain state between values produced and allows you to avoid callback functions.&lt;/p&gt;

&lt;p&gt;Let’s imagine that &lt;a href=&quot;http://developer.github.com&quot;&gt;Github API&lt;/a&gt; only allows to download an user gist per API call. In the example below we’re using a generator to create an iterator over user gists. To retrieve an user gist we’re maintaining the state between calls (the current page) and we’re retrieving the data only when is actually needed. Of course another approach could be to retrieve a chunk of gists and return them upon request, but it seems a good example about how to use generators :-). Kudos to &lt;a href=&quot;https://twitter.com/anarchyco&quot;&gt;@anarchyco&lt;/a&gt; for inspiring me to write this code.&lt;/p&gt;

&lt;script src=&quot;http://gist.github.com/3124648.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;To be continued…&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Fix latest commit branch using git</title>
   <link href="http://juandebravo.com/2012/06/26/git-tip-how-to-change-the-branch-of-a-commit/"/>
   <updated>2012-06-26T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2012/06/26/git-tip-how-to-change-the-branch-of-a-commit/</id>
   <content type="html">&lt;h1 id=&quot;introduction&quot;&gt;Introduction&lt;/h1&gt;

&lt;p&gt;I like git, I hope you like it too. I like using the &lt;a href=&quot;http://nvie.com/posts/a-successful-git-branching-model/&quot;&gt;git flow&lt;/a&gt; branching model while developing new features or fixing undesired bugs in a stable version.&lt;/p&gt;

&lt;p&gt;Sometimes while you’re starting a new feature, you forget changing your current branch and commit a change to the wrong branch (often develop).
Sometimes while you’re starting a new feature, you forget changing your current branch and end up committing a change to the wrong branch (often develop).&lt;/p&gt;

&lt;p&gt;Let’s walk through the steps required to move your latest commit from the wrong branch to the right one:&lt;/p&gt;

&lt;h1 id=&quot;1--prerequisites&quot;&gt;1.- Prerequisites&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;Create the repository with an initial content and create the develop branch.&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;bundle gem foo_bar
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;foo_bar
git commit &lt;span class=&quot;nt&quot;&gt;-am&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;first commit&quot;&lt;/span&gt;
git checkout &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; develop
&lt;span class=&quot;c&quot;&gt;# modify version.rb file to increase the version number&lt;/span&gt;
git commit &lt;span class=&quot;nt&quot;&gt;-am&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bump version&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;ul&gt;
  &lt;li&gt;Create your feature branch&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;git branch feature/hello
git lg                                                                                                                                   
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; d62b49a - &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;HEAD, feature/hello, develop&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; bump version - juandebravo &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;66 seconds ago&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; 9158f06 - &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;master&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; first commit - juandebravo &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;2 minutes ago&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;ul&gt;
  &lt;li&gt;Commit a change to develop (instead of your feature branch)&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;require &apos;foo_bar/version&apos;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;module FooBar&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;  def self.hello(name)&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;    print &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;hello #{name}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;  end&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;end&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; lib/foo_bar.rb
git commit &lt;span class=&quot;nt&quot;&gt;-am&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;add hello method&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;WRONG! You commit to develop instead of feature/hello&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;git lg
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; ecd59c3 - &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;HEAD, develop&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; add hello method - juandebravo &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;2 seconds ago&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; d62b49a - &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;feature/hello&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; bump version - juandebravo &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;40 minutes ago&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; 9158f06 - &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;master&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; first commit - juandebravo &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;40 minutes ago&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;2--fix-the-wrong-commit&quot;&gt;2.- Fix the wrong commit&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;Merge develop to your feature branch&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;git checkout feature/crud_users
git merge develop
git lg
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; ecd59c3 - &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;HEAD, feature/hello, develop&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; add hello method - juandebravo &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;3 minutes ago&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; d62b49a - bump version - juandebravo &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;43 minutes ago&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; 9158f06 - &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;master&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; first commit - juandebravo &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;44 minutes ago&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now you already have the change in your feature branch. Now it’s time to remove it from develop branch.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Remove the commit from develop branch&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;git checkout develop
git reset &lt;span class=&quot;nt&quot;&gt;--hard&lt;/span&gt; HEAD~1
git lg
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; ecd59c3 - &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;feature/hello&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; add hello method - juandebravo &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;4 minutes ago&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; d62b49a - &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;HEAD, develop&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; bump version - juandebravo &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;44 minutes ago&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; 9158f06 - &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;master&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; first commit - juandebravo &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;44 minutes ago&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;ul&gt;
  &lt;li&gt;That’s all!!&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Yet another blog in the world</title>
   <link href="http://juandebravo.com/2012/05/31/yet-another-blog-in-the-world/"/>
   <updated>2012-05-31T00:00:00+00:00</updated>
   <id>http://juandebravo.com/2012/05/31/yet-another-blog-in-the-world/</id>
   <content type="html">&lt;h1 id=&quot;hello-world&quot;&gt;Hello world&lt;/h1&gt;

&lt;p&gt;During the last months I’ve felt an increasing need to share my thoughts with the tech world for the following reasons:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;I think it’s a good way to keep on learning English. Yes fellas, I’ve been working on Shakespeare’s language for a while but there is a whole road of new words and expressions to take in. Sad but true. So, never give up. Learn!&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;One of my new year resolutions was to embrace a new programming language. It’s incredible how much you can learn in a travel like that and sometimes I need to share some bits of that new knowledge. Some of those might be could obvious to you but they are new to me that’s why they are here. As my motto says: “never stop learning”.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;why-jekyll-and-not-wordpress&quot;&gt;Why Jekyll and not Wordpress?&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;In 2011 I’d been working mainly in an innovation project where we had the chance to test and use different tools to build our platform and service. It was an awesome adventure. One of the things we did was creating all the documentation our service needed using &lt;a href=&quot;http://daringfireball.net/projects/markdown/&quot;&gt;Markdown&lt;/a&gt; format and running a &lt;a href=&quot;http://rake.rubyforge.org/&quot;&gt;Rake&lt;/a&gt; task to generate the HTML pages that any HTTP server in the world could serve. Yes, we did not need any hard editorial flow to follow, we were innovators. Kudos to &lt;a href=&quot;http://www.twitter.com/osuka&quot;&gt;@osuka&lt;/a&gt; for letting me that freedom.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;ruby, github and git are my tools of choice whenever I can use them and I’m a big fan of UNIX shell so it’s kind of familiar environment for me. Kudos to &lt;a href=&quot;http://pages.github.com/#using_jekyll_for_complex_layouts&quot;&gt;GitHub pages for supporting Jekyll&lt;/a&gt;. I can use git flow to write my blog!&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Last, but not least, my fellow &lt;a href=&quot;http://www.twitter.com/rafeca&quot;&gt;@rafeca&lt;/a&gt; started a blog during our international assignment in &lt;a href=&quot;http://www.jajah.com&quot;&gt;Jajah&lt;/a&gt;. I’m using &lt;a href=&quot;http://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt; and I have borrowed his layout to build this blog.  Hopefully I’ll write more often than he does, though. For me it’s also a way to share experiences with him now that ours careers have diverged :-) Please check &lt;a href=&quot;http://rafeca.com/2011/11/09/creating-this-blog/&quot;&gt;his explanation about how to create a blog like this from scratch&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;what-will-be-this-about&quot;&gt;What will be this about&lt;/h1&gt;

&lt;p&gt;Well, I’m always reading new stuff, you know, never stop learning. I’ll try to show some of the new stuff I’m reading about. At this point, could be something related to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;ruby, my programming language of choice.&lt;/li&gt;
  &lt;li&gt;python, the language I’m currently using more widely.&lt;/li&gt;
  &lt;li&gt;git, the SCM that is amazing IMO.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.adhearsion.com&quot;&gt;Adhearsion&lt;/a&gt;, the open source telephony framework I was actively contributing for some months and that is being leaded by the awesome Ben Klang, Ben Langfeld and Jason Goecke.&lt;/li&gt;
  &lt;li&gt;Freeswitch and ESL, the telephony platform I’m hacking with (not so often though)&lt;/li&gt;
  &lt;li&gt;Scala: learning Scala was my first new year resolution, I’ve started learning now and I do like to syntax. I don’t have yet a strong opinion about it that seems quite amazing.&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 

</feed>
