<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>La Nueva Escuela</title>
    <description>A seldomly updated log of stuff I'm into. Mostly about programming and tech.
</description>
    <link>http://www.ateijelo.com/</link>
    <atom:link href="http://www.ateijelo.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Sat, 28 Jan 2023 08:53:03 -0600</pubDate>
    <lastBuildDate>Sat, 28 Jan 2023 08:53:03 -0600</lastBuildDate>
    <generator>Jekyll v3.8.6</generator>
    
      <item>
        <title>Autolock idle Linux TTY Consoles</title>
        <description>&lt;p&gt;I usually lock my sessions, either manually or automatically after some idle time. At home that doesn’t make much of difference, but at the office, or in a public place, it’s important.&lt;/p&gt;

&lt;p&gt;However, I’ve always had this secret hole in my security: sometimes, because Linux’s graphical interfaces tend to die, I hit &lt;code class=&quot;highlighter-rouge&quot;&gt;Ctrl+Alt+F[1-6]&lt;/code&gt; to use the the &lt;em&gt;real&lt;/em&gt; TTYs, curiously named &lt;em&gt;virtual consoles&lt;/em&gt;, for the same historic reasons for which the V and the I in VIM mean &lt;em&gt;visual interface&lt;/em&gt;. Yeah, google it.&lt;/p&gt;

&lt;p&gt;But I digress. The virtual consoles are great, etc, etc. But when I’m done with them and return to my graphical environment &lt;em&gt;du jour&lt;/em&gt;, I almost never remember to log out from them. And since I usually use them to troubleshoot stuff, in many &lt;em&gt;many&lt;/em&gt; cases, I leave them around with the &lt;code class=&quot;highlighter-rouge&quot;&gt;root&lt;/code&gt; user fully logged in.&lt;/p&gt;

&lt;p&gt;That’s a problem, no need to explain it.&lt;/p&gt;

&lt;p&gt;I searched for a solution before and learned about Bash’s TMOUT environment variable, which you can set up to have Bash log out automatically after an idle timeout. But that’s fragile. Bash can only log out if you leave your session at the prompt. If you’re running anything else like Vim, Bash will not log out, regardless of how long you leave that untouched. I know I’ve had Vims in TTYs running for weeks without noticing it.&lt;/p&gt;

&lt;p&gt;Someone online had a slightly more effective approach: use &lt;code class=&quot;highlighter-rouge&quot;&gt;finger&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;who&lt;/code&gt; periodically to monitor idle time and kill the sessions that go over some limit. That’s more secure, sure. But it’s also too aggressive, because it may lose data. What if, for instance, you hadn’t saved what you typed in that Vim?&lt;/p&gt;

&lt;p&gt;So, today I came up with an alternative, using GNU &lt;em&gt;screen&lt;/em&gt;. The idea is simple, make your TTYs start &lt;em&gt;screen&lt;/em&gt; immediately after login. When that &lt;em&gt;screen&lt;/em&gt; exits, the session will end. And then idle-locking is trivial, &lt;em&gt;screen&lt;/em&gt; has a built-in solution. This is what I did:&lt;/p&gt;

&lt;p&gt;Add this at the end of to your &lt;code class=&quot;highlighter-rouge&quot;&gt;~/.bashrc&lt;/code&gt;:&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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$TERM&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;linux&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;tty&lt;/span&gt; | egrep &lt;span class=&quot;nt&quot;&gt;-q&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'^/dev/tty[[:digit:]]+$'&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;screen &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; ~/.ttyscreenrc
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;exec&lt;/code&gt; is important. It ensures that &lt;code class=&quot;highlighter-rouge&quot;&gt;screen&lt;/code&gt; will replace &lt;code class=&quot;highlighter-rouge&quot;&gt;bash&lt;/code&gt;, in the same process   and it’s what guarantees that when &lt;code class=&quot;highlighter-rouge&quot;&gt;screen&lt;/code&gt; ends the session will end too.&lt;/p&gt;

&lt;p&gt;Create a particular &lt;em&gt;screenrc&lt;/em&gt; for this. As seen above, I called it &lt;code class=&quot;highlighter-rouge&quot;&gt;~/.ttyscreenrc&lt;/code&gt;, with this content:&lt;/p&gt;

&lt;div class=&quot;language-conf 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;n&quot;&gt;startup_message&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;off&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;idle&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;180&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lockscreen&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And change that file to suit your preferences. I put 180 seconds (3 minutes).&lt;/p&gt;

&lt;p&gt;And that’s it. Your TTYs will lock and ask you for a password after the configured idle timeout. And you won’t lose any work.&lt;/p&gt;

&lt;p&gt;Share it!&lt;/p&gt;
</description>
        <pubDate>Wed, 02 May 2018 16:55:43 -0500</pubDate>
        <link>http://www.ateijelo.com/blog/2018/05/02/lock-linux-tty-consoles-on-timeout</link>
        <guid isPermaLink="true">http://www.ateijelo.com/blog/2018/05/02/lock-linux-tty-consoles-on-timeout</guid>
        
        
        <category>ssh</category>
        
        <category>keys</category>
        
        <category>known-hosts</category>
        
        <category>host-keys</category>
        
        <category>proxy</category>
        
        <category>tunnel</category>
        
      </item>
    
      <item>
        <title>SSH Keys - A Lesson for the Future Me</title>
        <description>&lt;p&gt;When I ssh from one system to another on my own network, or between virtual machines,
I usually don’t pay much attention to these warnings:&lt;/p&gt;

&lt;center&gt;&lt;pre&gt;
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
&lt;/pre&gt;&lt;/center&gt;

&lt;p&gt;since I know no one is meddling with my network and I know that’s the result of
me reinstalling VMs or reusing IPs etc.&lt;/p&gt;

&lt;p&gt;But when I see that while trying to log in to a remote VPS, which I know has been running for a long
time without changing either name, ip, or SSH host keys, then I DO WORRY. And that happened to
me this very morning, when attempting a login from my laptop.&lt;/p&gt;

&lt;p&gt;I’m too much of a nobody to be the target of any hacking, but still, I need to know
why I’m getting that warning before I can continue and log in. Thinking “nah, that’s probably nothing”
is surely what happens right before you’re hacked for real.&lt;/p&gt;

&lt;p&gt;My first step was to try to ssh from a different network and that worked without warning,
which was a good sign, regarding my VPS, but it meant that either my &lt;code class=&quot;highlighter-rouge&quot;&gt;~/.ssh/known_hosts&lt;/code&gt; had something
weird or I was indeed being attacked, however unlikely.&lt;/p&gt;

&lt;p&gt;So all I had left was to think hard and try to remember precisely all I had done since the
last time I logged in “warning-free”. And I found the real reason in my bash history:&lt;/p&gt;

&lt;pre style=&quot;font-size: 80%&quot;&gt;
ssh ateijelo@&lt;b style=&quot;color: red&quot;&gt;vps1&lt;/b&gt;.example.com -o &quot;ProxyCommand proxytunnel -d &lt;b style=&quot;color: green&quot;&gt;vps2&lt;/b&gt;.example.com:443 ....&quot;
&lt;/pre&gt;

&lt;p&gt;That was it. I tried to get to &lt;strong&gt;vps1&lt;/strong&gt; through a restrictive http proxy by using a second server (&lt;strong&gt;vps2&lt;/strong&gt;) that had ssh listening on port 443. And usually, when doing that, I paid little attention to what I wrote after my username &lt;code class=&quot;highlighter-rouge&quot;&gt;ateijelo@...&lt;/code&gt; in the command line, since that wouldn’t dictate how to get to the server. It would be the &lt;code class=&quot;highlighter-rouge&quot;&gt;ProxyCommand&lt;/code&gt; that took care of it.&lt;/p&gt;

&lt;p&gt;But I learned today that what you write there &lt;em&gt;does&lt;/em&gt; matter. It determines what gets written to &lt;code class=&quot;highlighter-rouge&quot;&gt;~/.ssh/known_hosts&lt;/code&gt; and in this case it ended up associating the host key of &lt;strong&gt;vps2&lt;/strong&gt; to &lt;strong&gt;vps1&lt;/strong&gt;. The right thing to do is simple: make sure the hostname in the ssh command matches the destination of the proxy tunnel. Like this:&lt;/p&gt;

&lt;pre style=&quot;font-size: 80%&quot;&gt;
ssh ateijelo@&lt;b style=&quot;color: green&quot;&gt;vps2&lt;/b&gt;.example.com -o &quot;ProxyCommand proxytunnel -d &lt;b style=&quot;color: green&quot;&gt;vps2&lt;/b&gt;.example.com:443 ....&quot;
&lt;/pre&gt;
</description>
        <pubDate>Wed, 06 Sep 2017 11:49:34 -0500</pubDate>
        <link>http://www.ateijelo.com/blog/2017/09/06/ssh-keys-lesson-future-me</link>
        <guid isPermaLink="true">http://www.ateijelo.com/blog/2017/09/06/ssh-keys-lesson-future-me</guid>
        
        
        <category>ssh</category>
        
        <category>keys</category>
        
        <category>known-hosts</category>
        
        <category>host-keys</category>
        
        <category>proxy</category>
        
        <category>tunnel</category>
        
      </item>
    
      <item>
        <title>An Effective Fix for the Switch Pro Controller D-Pad Issues</title>
        <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Open the controller and cover the inner half of the metallic contacts below the D-Pad with some adhesive tape. See pictures below.&lt;/p&gt;

&lt;h3 id=&quot;the-problem&quot;&gt;The Problem&lt;/h3&gt;

&lt;p&gt;This is the Nintendo Switch’s Pro Controller:&lt;/p&gt;

&lt;center&gt;
  &lt;img class=&quot;noshadow&quot; src=&quot;../../../../assets/img/switch-pro-01.jpg&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;It was launched along the Switch back in March, and from day one, some people have been reporting that the D-Pad registers unwanted &lt;em&gt;Up&lt;/em&gt; and &lt;em&gt;Down&lt;/em&gt; inputs when pressing &lt;em&gt;Left&lt;/em&gt; or &lt;em&gt;Right&lt;/em&gt;. [citations]&lt;/p&gt;

&lt;p&gt;I finally got one yesterday and it was, indeed, a defective one. The test that many people performed, playing Puyo Puyo Tetris, failed for me as well. While I could score over 200k points in single player Tetris with the Joy Cons, I couldn’t get to 100k when using the Pro Controller’s D-Pad. And that was mostly because I kept getting unintentional fast-drops.&lt;/p&gt;

&lt;p&gt;So, after less that 24 hours of getting it, my Pro Controller looked like this:&lt;/p&gt;

&lt;center&gt;
 &lt;a href=&quot;../../../../assets/img/switch-pro-05.jpg&quot;&gt;&lt;img src=&quot;../../../../assets/img/switch-pro-05-small.jpg&quot; /&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;/center&gt;

&lt;h3 id=&quot;a-simple--effective-solution&quot;&gt;A Simple &amp;amp; Effective Solution&lt;/h3&gt;

&lt;p&gt;I looked around and found several brave souls [citations] that opened their controllers and tried to fix them by modifying some parts or padding in some places with cardboard. But I didn’t want to trim or file down any part, and I wasn’t happy with adding padding that could, with time, change in shape or move out of place, forcing me to open the controller again to “re-fix” it.&lt;/p&gt;

&lt;p&gt;While I was still understanding the “mechanical problem”, I noticed that, in the PCB, the gap between the metallic contacts of each direction is aligned with the center. The black rubber thingy that closes each button’s circuit needs only touch one tiny part of both contacts to work.&lt;/p&gt;

&lt;p&gt;I suspected that unintended touches were rubbing just slightly the inner parts of this metallic contacts:&lt;/p&gt;

&lt;center&gt;
  &lt;img src=&quot;../../../../assets/img/switch-pro-02.jpg&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;So I tried reducing the available contact area by covering just a bit beyond the inner half of all contacts with tape:&lt;/p&gt;

&lt;center&gt;
  &lt;img src=&quot;../../../../assets/img/switch-pro-03.jpg&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;This is my (not too pretty) implementation with transparent adhesive, which is also visible in the images above:&lt;/p&gt;

&lt;center&gt;
 &lt;a href=&quot;../../../../assets/img/switch-pro-04.jpg&quot;&gt;&lt;img src=&quot;../../../../assets/img/switch-pro-04-small.jpg&quot; /&gt;&lt;/a&gt;

&lt;/center&gt;

&lt;h3 id=&quot;results&quot;&gt;Results&lt;/h3&gt;

&lt;p&gt;This solution is simple since we don’t need to modify anything. And it’s mechanically durable, since the tape rests on the PCB and the button is just pressing down on it.&lt;/p&gt;

&lt;p&gt;The result is quite good. Unlike some other solutions I still can get &lt;em&gt;Up&lt;/em&gt; and &lt;em&gt;Down&lt;/em&gt; when pressing &lt;em&gt;Left&lt;/em&gt; or &lt;em&gt;Right&lt;/em&gt; if I want to, and I think that’s ok. But I don’t get them unintentionally except if I do &lt;em&gt;Left-Right-Left-Right…&lt;/em&gt; repeatedly and quickly.&lt;/p&gt;

&lt;p&gt;I just played a round of single-player Tetris after this fix and I got to 190k points without one single unwanted fast-drop.&lt;/p&gt;

&lt;p&gt;Not too shabby ;)&lt;/p&gt;

&lt;h3 id=&quot;ps-thank-you&quot;&gt;PS: Thank You&lt;/h3&gt;

&lt;p&gt;I’m happy to know my controller has this message from Nintendo inside it:&lt;/p&gt;

&lt;center&gt;
 &lt;img alt=&quot;Switch Pro Controller PCB contains the message THX2 ALLGAMEFANS!&quot; src=&quot;../../../../assets/img/switch-pro-06.jpg&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;Thank you, Nintendo.&lt;/p&gt;
</description>
        <pubDate>Wed, 12 Jul 2017 03:45:24 -0500</pubDate>
        <link>http://www.ateijelo.com/blog/2017/07/12/effective-fix-switch-pro-controller-dpad-issues</link>
        <guid isPermaLink="true">http://www.ateijelo.com/blog/2017/07/12/effective-fix-switch-pro-controller-dpad-issues</guid>
        
        
        <category>nintendo</category>
        
        <category>switch</category>
        
        <category>pro</category>
        
        <category>controller</category>
        
        <category>dpad</category>
        
        <category>ghost-input</category>
        
        <category>diy</category>
        
        <category>fix</category>
        
      </item>
    
      <item>
        <title>BotW Panoramas</title>
        <description>&lt;h3 id=&quot;creating-botw-panoramic-pictures&quot;&gt;Creating BotW Panoramic Pictures&lt;/h3&gt;

&lt;center&gt;
  &lt;a href=&quot;../../../../assets/img/botw-01-hateno.jpg&quot;&gt;&lt;img src=&quot;../../../../assets/img/botw-01-hateno-small.jpg&quot; /&gt;&lt;/a&gt;
&lt;/center&gt;

&lt;p&gt;Back in February, &lt;a href=&quot;https://www.reddit.com/r/NintendoSwitch/comments/68i2py/creating_botw_landscape_panoramas_using_the/&quot;&gt;this post&lt;/a&gt; was made in Reddit and I found it fascinating. The world of The Legend of Zelda: Breath of the Wild is expansive and gorgeous. And those panoramic views were great.&lt;/p&gt;

&lt;p&gt;That post relied on one key idea: when aiming with the Phrenic Bow, the entire bow disappears from the screen, leaving just the cross-hair. However, most of the process was mostly manual. I wanted to fix that and then improve on some other aspects. My two main goals were:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Make it as automatic as possible&lt;/li&gt;
  &lt;li&gt;Base it on open source tools&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The current result is on &lt;a href=&quot;https://github.com/ateijelo/botw-panoramas&quot;&gt;GitHub&lt;/a&gt;. The code depends on Python 2, OpenCV and Hugin.&lt;/p&gt;

&lt;p&gt;If you got this far, I’ll use the opportunity to request help with Hugin. I chose it because it was what I found when looking for open-source tools for making panoramas. But my previous experience with it was close to zero, and I’d like people with more experience to take a look at what I did and suggest improvements.&lt;/p&gt;

&lt;h3 id=&quot;the-climbing-method&quot;&gt;The &lt;em&gt;Climbing&lt;/em&gt; Method&lt;/h3&gt;

&lt;p&gt;There’s an alternative to using the Phrenic Bow method, that I like to call the “climbing” method. It was suggested in &lt;a href=&quot;https://www.reddit.com/r/NintendoSwitch/comments/68i2py/creating_botw_landscape_panoramas_using_the/dgyoehm/&quot;&gt;this comment&lt;/a&gt; to the original post in Reddit. When Link is climbing a surface, you can move the camera to between Link and said surface, and then Link disappears, giving an almost entirely clear screen except for the hearts.&lt;/p&gt;

&lt;p&gt;The field of view with this method is bigger, requiring many fewer pictures to assemble a large view. However, everything is further away from the observer, giving a lot less details in the resulting panorama.&lt;/p&gt;

&lt;p&gt;The last picture of the gallery at the end of this post is an example of a panorama built with that method.&lt;/p&gt;

&lt;p&gt;The rest of this post focuses on the &lt;em&gt;Phrenic Bow&lt;/em&gt; method, which is harder, but gives panoramas with more detail. And the code is written for the Phrenic Bow method only.&lt;/p&gt;

&lt;h3 id=&quot;instructions&quot;&gt;Instructions&lt;/h3&gt;

&lt;p&gt;The code is straightforward, you run the Python script and give it the images as arguments. Wait for a while, and you’ll hopefully get a properly composed panoramic picture. But to get there, you need to follow some guidelines.&lt;/p&gt;

&lt;h4 id=&quot;1-dependencies&quot;&gt;1. Dependencies&lt;/h4&gt;

&lt;p&gt;The code was developed on Debian, and it depends on these packages:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;python-opencv&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;hugin-tools&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, making this run in Mac or Windows should not be hard, as these are open-source.&lt;/p&gt;

&lt;h4 id=&quot;2-taking-the-screenshots&quot;&gt;2. Taking the Screenshots&lt;/h4&gt;

&lt;p&gt;For best results, follow this rules when taking the screenshots. I did all this on a Nintendo Switch. I don’t know if this can be done on the Wii U’s version of the game.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Use the Phrenic Bow&lt;/strong&gt;. It can be found in … (can’t remember, tell me in the comments below and I’ll add it here)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Use the Pro HUD&lt;/strong&gt;. This removes the mini-map, the weather forecast, etc., leaving a cleaner image for the panorama.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Make the pictures overlap&lt;/strong&gt;. The more they overlap, the better the results. But try to find a balance between &lt;em&gt;overlap&lt;/em&gt; and &lt;em&gt;total number of pictures&lt;/em&gt;. The stitching progress gets quadratically slower as the number of pictures increases. I try to stay below 100 pictures.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Hold the ZR button&lt;/strong&gt; when taking the screenshot. This is optional, but highly recommended. That brings the three lines of the cross-hair closer to the center.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Zero Arrows&lt;/strong&gt;. Also recommended. Use an arrow type for which you have no arrows. When you’re out of arrows and hold ZR, the game fades out the cross-hair a bit, improving the result of the OpenCV’s &lt;em&gt;in-paint&lt;/em&gt; call that removes it.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;center&gt;
  &lt;img class=&quot;noshadow&quot; src=&quot;../../../../assets/img/botw-03-arrows-zr.jpg&quot; /&gt;
  &lt;br /&gt;
  &lt;span&gt;&lt;i&gt;The code works best with no arrows and holding ZR,&lt;br /&gt;(but has options for the other scenarios too)&lt;/i&gt;&lt;/span&gt;.
&lt;/center&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Column-first&lt;/strong&gt;. This is optional, but I find it gives me better results: grab your screenshots in a column-first fashion. I find it easier to ensure I don’t leave blind spots in the panorama.&lt;/li&gt;
&lt;/ul&gt;

&lt;center&gt;
&lt;img src=&quot;../../../../assets/img/botw-04-column-first.jpg&quot; /&gt;
&lt;br /&gt;

&lt;span&gt;&lt;i&gt;Take screenshots in a column-first fashion&lt;/i&gt;&lt;/span&gt;.
&lt;/center&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Disable motion-controls&lt;/strong&gt;. Also optional, but I found it easer to control the placement of each screenshots if I didn’t have to worry about motion controls. They’re great for aiming; not so much for this.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;3-running-the-code&quot;&gt;3. Running the code&lt;/h4&gt;

&lt;p&gt;Transfer the pictures to your computer. Remember to turn off your Switch (hold power down until the power options menu shows up). Only then extract your MicroSD card. If you pull it out while the system is running, you risk corrupting your data. (Side question: is there a better way to bulk-transfer pictures from your Switch?)&lt;/p&gt;

&lt;p&gt;Put all the pictures from the panorama you want to create in an empty directory and run:&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;python2 botw-panorama.py &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.jpg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Of course, adjust the path to &lt;code class=&quot;highlighter-rouge&quot;&gt;botw-panorama.py&lt;/code&gt; accordingly.&lt;/p&gt;

&lt;p&gt;If you don’t want to hold ZR when taking your screenshots, or you have a lot of arrows of every type you don’t want to throw away you can tell that to the program:&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;python2 botw-panorama.py &lt;span class=&quot;nt&quot;&gt;--arrows&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;999 &lt;span class=&quot;nt&quot;&gt;--holding-zr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;no &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.jpg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will use a different mask to remove the cross-hair and the number of arrows.&lt;/p&gt;

&lt;h4 id=&quot;4-manual-tweaks&quot;&gt;4. Manual Tweaks&lt;/h4&gt;

&lt;p&gt;The output of the code will most certainly not be a rectangular image. You will need to crop it manually. Like this:&lt;/p&gt;

&lt;center&gt;
  &lt;img src=&quot;../../../../assets/img/botw-05-hugin-output.jpg&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;Hugin knows how to crop that automatically, but I’ve found that most of the time I want to make different trade-offs to those of its algorightms. So I do it manually.&lt;/p&gt;

&lt;p&gt;Sometimes you get a really weird result, but one that it’s just a &lt;em&gt;Move/Center&lt;/em&gt; operation away from a good one. For those cases, the tools leaves around the intermediate Hugin projects it creates. Open one of those, make whatever changes you deem necessary, and then run the tool again with &lt;code class=&quot;highlighter-rouge&quot;&gt;--first-step=N&lt;/code&gt; to start from a given step instead of from the beginning.&lt;/p&gt;

&lt;h3 id=&quot;gallery&quot;&gt;Gallery&lt;/h3&gt;

&lt;p&gt;Here are some of my own creations. Click for a closer look.&lt;/p&gt;

&lt;center&gt;
&lt;a href=&quot;../../../../assets/img/botw-08-tabantha.jpg&quot;&gt;&lt;img src=&quot;../../../../assets/img/botw-08-tabantha-small.jpg&quot; /&gt;&lt;/a&gt;
&lt;br /&gt;

&lt;span&gt;&lt;i&gt;From somewhere in Tabantha (I don't really remember where)&lt;/i&gt;&lt;/span&gt;.
&lt;/center&gt;

&lt;center&gt;
&lt;a href=&quot;../../../../assets/img/botw-09-temple-of-time.jpg&quot;&gt;&lt;img src=&quot;../../../../assets/img/botw-09-temple-of-time-small.jpg&quot; /&gt;&lt;/a&gt;
&lt;br /&gt;

&lt;span&gt;&lt;i&gt;From the Temple of Time, in the Great Plateau&lt;/i&gt;&lt;/span&gt;.
&lt;/center&gt;

&lt;center&gt;
&lt;a href=&quot;../../../../assets/img/botw-11-satori-mountain.jpg&quot;&gt;&lt;img src=&quot;../../../../assets/img/botw-11-satori-mountain-small.jpg&quot; /&gt;&lt;/a&gt;
&lt;br /&gt;

&lt;span&gt;&lt;i&gt;Near the summit of Satori Mountain&lt;/i&gt;&lt;/span&gt;.
&lt;/center&gt;

&lt;center&gt;
&lt;a href=&quot;../../../../assets/img/botw-10-lurelin-village.jpg&quot;&gt;&lt;img src=&quot;../../../../assets/img/botw-10-lurelin-village-small.jpg&quot; /&gt;&lt;/a&gt;
&lt;br /&gt;

&lt;span&gt;&lt;i&gt;Lurelin Village at dawn&lt;/i&gt;&lt;/span&gt;.
&lt;/center&gt;

&lt;center&gt;
&lt;a href=&quot;../../../../assets/img/botw-12-gerudo-desert.jpg&quot;&gt;&lt;img src=&quot;../../../../assets/img/botw-12-gerudo-desert-small.jpg&quot; /&gt;&lt;/a&gt;
&lt;br /&gt;

&lt;span&gt;&lt;i&gt;Part of the Gerudo Desert from Wasteland Tower&lt;/i&gt;&lt;/span&gt;.
&lt;/center&gt;

&lt;center&gt;
&lt;a href=&quot;../../../../assets/img/botw-14-tarry-town-at-night.jpg&quot;&gt;&lt;img src=&quot;../../../../assets/img/botw-14-tarry-town-at-night-small.jpg&quot; /&gt;&lt;/a&gt;
&lt;br /&gt;

&lt;span&gt;&lt;i&gt;Tarry Town at night&lt;/i&gt;&lt;/span&gt;.
&lt;/center&gt;

&lt;center&gt;
&lt;a href=&quot;../../../../assets/img/botw-15-near-goron-city.jpg&quot;&gt;&lt;img src=&quot;../../../../assets/img/botw-15-near-goron-city-small.jpg&quot; /&gt;&lt;/a&gt;
&lt;br /&gt;

&lt;span&gt;&lt;i&gt;Night from a rock near Goron City&lt;/i&gt;&lt;/span&gt;
&lt;/center&gt;

&lt;center&gt;
&lt;a href=&quot;../../../../assets/img/botw-16-a-peaceful-afternoon-by-woodland-stable.jpg&quot;&gt;&lt;img src=&quot;../../../../assets/img/botw-16-a-peaceful-afternoon-by-woodland-stable-small.jpg&quot; /&gt;&lt;/a&gt;
&lt;br /&gt;

&lt;span&gt;&lt;i&gt;A peaceful afternoon by Woodland Stable&lt;/i&gt;&lt;/span&gt;
&lt;/center&gt;

&lt;center&gt;
&lt;a href=&quot;../../../../assets/img/botw-13-climbing-method.jpg&quot;&gt;&lt;img src=&quot;../../../../assets/img/botw-13-climbing-method-small.jpg&quot; /&gt;&lt;/a&gt;
&lt;br /&gt;

&lt;span&gt;&lt;i&gt;Hateno and the Necluda Sea from the Ancient Lab (using the Climbing method)&lt;/i&gt;&lt;/span&gt;.
&lt;/center&gt;

&lt;p&gt;Well, fire away in the comments. Suggestions for improvements, GitHub pull-requests and flame wars are all welcome alike.&lt;/p&gt;

</description>
        <pubDate>Sat, 24 Jun 2017 15:13:20 -0500</pubDate>
        <link>http://www.ateijelo.com/blog/2017/06/24/botw-panoramas</link>
        <guid isPermaLink="true">http://www.ateijelo.com/blog/2017/06/24/botw-panoramas</guid>
        
        
        <category>python</category>
        
        <category>opencv</category>
        
        <category>hugin</category>
        
        <category>zelda</category>
        
        <category>botw</category>
        
        <category>panorama</category>
        
      </item>
    
      <item>
        <title>System Heaven</title>
        <description>&lt;h2 id=&quot;system-heaven&quot;&gt;System Heaven&lt;/h2&gt;

&lt;p&gt;System Heaven is an easy and secure way of running subprocesses. It is more convenient that &lt;code class=&quot;highlighter-rouge&quot;&gt;subprocess&lt;/code&gt;, particularly when pipes are involved. And it’s more secure than &lt;code class=&quot;highlighter-rouge&quot;&gt;os.system&lt;/code&gt; because it never uses a shell underneath and it’s not vulnerable to &lt;a href=&quot;https://en.wikipedia.org/wiki/Shell_injection&quot;&gt;shell injections&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;the-problems-with-ossystem&quot;&gt;The problems with &lt;em&gt;os.system&lt;/em&gt;&lt;/h3&gt;

&lt;p&gt;While &lt;code class=&quot;highlighter-rouge&quot;&gt;os.system&lt;/code&gt; is simple and convenient, it has several downsides:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Insecure:&lt;/strong&gt; As long as the command to execute is fixed, &lt;code class=&quot;highlighter-rouge&quot;&gt;os.system&lt;/code&gt;, as its underlying call &lt;code class=&quot;highlighter-rouge&quot;&gt;system&lt;/code&gt;, just works. But as soon as some part of it is variable, there’s a risk of injection. Escaping helps, but it’s a headache, and it’ll break sooner or later.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Inconsistent:&lt;/strong&gt; The behavior of &lt;code class=&quot;highlighter-rouge&quot;&gt;os.system&lt;/code&gt; depends of the underlying shell and the operating system it’s running on.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Limited:&lt;/strong&gt; The standard output and error output of the command can not be captured with &lt;code class=&quot;highlighter-rouge&quot;&gt;os.system&lt;/code&gt;. The return value of &lt;code class=&quot;highlighter-rouge&quot;&gt;os.system&lt;/code&gt; is usually the exit status of the command, but it again depends of the operating system and the interpreter.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;the-problem-with-subprocess&quot;&gt;The problem with &lt;em&gt;subprocess&lt;/em&gt;&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;subprocess&lt;/code&gt; module actually does its job rather well. It solves successfully the issues with &lt;code class=&quot;highlighter-rouge&quot;&gt;os.system&lt;/code&gt; and even integrates the capabilites of &lt;code class=&quot;highlighter-rouge&quot;&gt;os.spawn&lt;/code&gt; and the old &lt;code class=&quot;highlighter-rouge&quot;&gt;Popen&lt;/code&gt;. Its main downside is that some things, particularly pipes, can get cumbersome very quickly.&lt;/p&gt;

&lt;p&gt;For instance, these shell backquotes:&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;nv&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;dmesg | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;hda&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;become the following:&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;subprocess&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Popen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PIPE&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Popen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;dmesg&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PIPE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;p2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Popen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;grep&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;hda&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stdin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PIPE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Allow p1 to receive a SIGPIPE if p2 exits.
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;communicate&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;the-way-of-system-heaven&quot;&gt;The way of System Heaven&lt;/h3&gt;

&lt;p&gt;The core of System Heaven is the fuction &lt;code class=&quot;highlighter-rouge&quot;&gt;sh&lt;/code&gt;. The name of the function, and of the library, is intentionally based on that of the common Unix shells. But System Heaven’s &lt;code class=&quot;highlighter-rouge&quot;&gt;sh&lt;/code&gt; is not a shell, nor it ever uses one underneath.&lt;/p&gt;

&lt;p&gt;The most basic call looks like this:&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;systemheaven&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sh&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;wget http://example.com/something.zip&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;We can, however, use variables, which add flexibility while avoiding shell injections:&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;n&quot;&gt;sh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;wget $url&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://example.com/something.zip&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;You may wonder why isn’t that just as vulnerable to injections as &lt;code class=&quot;highlighter-rouge&quot;&gt;os.system&lt;/code&gt;. The difference stems from the fact that System Heaven does an intentionally limited parsing of its command line and variables become &lt;strong&gt;one single element&lt;/strong&gt; of the list that is passed to &lt;code class=&quot;highlighter-rouge&quot;&gt;Popen&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Even if a variable has spaces or other characters that would be special to a shell, it’s safe to use it with System Heaven:&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;nb&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Some Docs ; rm -rf /&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ls -l $dir&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# totally safe
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That would produce, at worst, a &lt;em&gt;No such file or directory&lt;/em&gt; from &lt;code class=&quot;highlighter-rouge&quot;&gt;ls&lt;/code&gt;. This behavior is similar to what module &lt;code class=&quot;highlighter-rouge&quot;&gt;sqlite3&lt;/code&gt; does with the question marks to avoid SQL injections.&lt;/p&gt;

&lt;p&gt;A variable can become more than one argument if, instead of a string, you pass an iterable. For instance:&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;n&quot;&gt;sh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;sha256sum $files&quot;&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;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;file1.iso&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;file2.iso&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;or better:&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;glob&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;glob&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;sha256sum $files&quot;&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;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;glob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;*.iso&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;Pipelines can be built very easily with &lt;code class=&quot;highlighter-rouge&quot;&gt;|&lt;/code&gt;:&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;n&quot;&gt;sh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ls $dir | grep txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/home/user&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;The longer the pipeline, the better it feels to use &lt;code class=&quot;highlighter-rouge&quot;&gt;sh&lt;/code&gt;:&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;n&quot;&gt;sh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ls dir | grep a | grep b | grep c&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;If you want to read the output of a command, put a &lt;code class=&quot;highlighter-rouge&quot;&gt;|&lt;/code&gt; at the end:&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;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ls | wc -l |&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;stdout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&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;With this capability, the pipe of the previous section becomes:&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;n&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'dmesg | grep hda |'&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;stdout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&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;To send input to a command, put the &lt;code class=&quot;highlighter-rouge&quot;&gt;|&lt;/code&gt; in front of the line:&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;n&quot;&gt;cmd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'| grep py$'&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;filename&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;listdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdin&lt;/span&gt;&lt;span class=&quot;o&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;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&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;'utf8'&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;You can put &lt;code class=&quot;highlighter-rouge&quot;&gt;|&lt;/code&gt; in both the beginning and the end of the line. But be careful of potential deadlocks.&lt;/p&gt;

&lt;p&gt;Some design choices were driven by this goal. In particular, System Heaven avoids any string manipulation, as explained in the next sections.&lt;/p&gt;

&lt;h3 id=&quot;quoting--escaping&quot;&gt;Quoting &amp;amp; Escaping&lt;/h3&gt;

&lt;p&gt;There are &lt;em&gt;no&lt;/em&gt; quoting mechanisms in System Heaven. Neither &lt;code class=&quot;highlighter-rouge&quot;&gt;&quot;&lt;/code&gt;, nor &lt;code class=&quot;highlighter-rouge&quot;&gt;'&lt;/code&gt;, nor &lt;code class=&quot;highlighter-rouge&quot;&gt;\&lt;/code&gt; have any special meaning. Anywhere you feel inclined to use quoting or escaping, use a variable.&lt;/p&gt;

&lt;p&gt;For instance, if you say:&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;n&quot;&gt;sh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'ls -l &quot;Some Documents&quot;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# may not do what you're thinking
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;that will become something like:&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;n&quot;&gt;subprocess&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Popen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'ls'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'-l'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'&quot;Some'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'Documents&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;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and you will be asking &lt;code class=&quot;highlighter-rouge&quot;&gt;ls&lt;/code&gt; to list &lt;strong&gt;two&lt;/strong&gt; directories: &lt;code class=&quot;highlighter-rouge&quot;&gt;&quot;Some&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Documents&quot;&lt;/code&gt;. Probably not what you originally meant. A similar thing would happend with &lt;code class=&quot;highlighter-rouge&quot;&gt;ls -l Some\ Documents&lt;/code&gt;. That would list two directories, the first one of which happens to end with a backslash.&lt;/p&gt;

&lt;p&gt;In any of those cases, say the following instead:&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;n&quot;&gt;sh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'ls -l $dir'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Some Documents'&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;h3 id=&quot;variables&quot;&gt;Variables&lt;/h3&gt;

&lt;p&gt;Variables only work when used as a whole word. That means that a &lt;code class=&quot;highlighter-rouge&quot;&gt;$&lt;/code&gt; sign in the middle or the end of a word will be passed untouched to the subprocess. For instance, the following:&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;n&quot;&gt;sh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'ls -l /media/$user'&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;s&quot;&gt;&quot;ubuntu&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# won't do what it seems
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;will become:&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;n&quot;&gt;subprocess&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'ls'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'-l'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'/media/$user'&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;and the &lt;code class=&quot;highlighter-rouge&quot;&gt;user&lt;/code&gt; argument will just go unused.&lt;/p&gt;

&lt;p&gt;Similarly there’s no &lt;code class=&quot;highlighter-rouge&quot;&gt;${var}&lt;/code&gt; syntax. You could use it, but then your &lt;em&gt;kwargs&lt;/em&gt; would need a &lt;code class=&quot;highlighter-rouge&quot;&gt;&quot;{var}&quot;&lt;/code&gt; key. System Heaven’s parsing is intentionally limited and transparent: a variable is a word that starts with &lt;code class=&quot;highlighter-rouge&quot;&gt;$&lt;/code&gt; and the rest of the word is the name of the variable –without restrictions– and will be looked up, untouched, in &lt;em&gt;kwargs&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The right way to do the thing above is:&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;n&quot;&gt;sh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'ls -l $dir'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/media/&quot;&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;String manipulation is the responsibility of the caller.&lt;/p&gt;

&lt;h3 id=&quot;special-variables&quot;&gt;Special Variables&lt;/h3&gt;

&lt;p&gt;Some keyword arguments, like &lt;code class=&quot;highlighter-rouge&quot;&gt;_cwd&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;_env&lt;/code&gt; are reserved for tweaking the behavior of &lt;code class=&quot;highlighter-rouge&quot;&gt;sh&lt;/code&gt;. Avoid using variables starting with &lt;code class=&quot;highlighter-rouge&quot;&gt;_&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;examples&quot;&gt;Examples&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;The following Bash pipeline:&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;nv&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;wc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;would become this System Heaven invocation:&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;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ls | wc -l |&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;stdout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&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;/li&gt;
  &lt;li&gt;
    &lt;p&gt;System Heaven variables can be iterables. This Bash line:&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;nv&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.txt | &lt;span class=&quot;nb&quot;&gt;wc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;becomes&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;glob&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;glob&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ls $files | wc -l |&quot;&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;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;glob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;*.txt&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;stdout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&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;/li&gt;
  &lt;li&gt;
    &lt;p&gt;You can change the current working directory with &lt;code class=&quot;highlighter-rouge&quot;&gt;_cwd&lt;/code&gt;. This Bash line:&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;cd&lt;/span&gt; /home/user
&lt;span class=&quot;nv&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.txt | &lt;span class=&quot;nb&quot;&gt;wc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;becomes:&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;glob&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;glob&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ls $files | wc -l |&quot;&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;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;glob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;*.txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
           &lt;span class=&quot;n&quot;&gt;_cwd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/home/user&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;stdout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&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;/li&gt;
&lt;/ul&gt;

</description>
        <pubDate>Thu, 09 Mar 2017 21:35:52 -0600</pubDate>
        <link>http://www.ateijelo.com/blog/2017/03/09/system-heaven</link>
        <guid isPermaLink="true">http://www.ateijelo.com/blog/2017/03/09/system-heaven</guid>
        
        
        <category>python</category>
        
        <category>subprocess</category>
        
        <category>system</category>
        
        <category>heaven</category>
        
      </item>
    
      <item>
        <title>Linux Console &amp; High DPI Displays</title>
        <description>&lt;p&gt;I recently installed Debian 8 on a MacBook Pro with a hi-dpi display, or as Apple calls it, a Retina Display. I used a &lt;em&gt;netinst&lt;/em&gt; installer, which is very small, but leaves you, right after the installation, with nothing but a Linux text console.&lt;/p&gt;

&lt;p&gt;And the font is tiny!&lt;/p&gt;

&lt;p&gt;Luckily, there’s a remedy for this. First, squint your eyes and login, and set the font directly with:&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;setfont Uni3-Terminus32x16
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you want to try other fonts, check under &lt;code class=&quot;highlighter-rouge&quot;&gt;/usr/share/consolefonts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To make that change permanent, edit &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/default/console-setup&lt;/code&gt; and make the following three variables look like this:&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;nv&quot;&gt;CODESET&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Uni3&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;FONTFACE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Terminus&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;FONTSIZE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;32x16&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now you can enjoy a readable font size and that will get applied on every boot.&lt;/p&gt;
</description>
        <pubDate>Wed, 01 Feb 2017 00:11:34 -0600</pubDate>
        <link>http://www.ateijelo.com/blog/2017/02/01/linux-console-high-dpi-display</link>
        <guid isPermaLink="true">http://www.ateijelo.com/blog/2017/02/01/linux-console-high-dpi-display</guid>
        
        
        <category>linux</category>
        
        <category>console</category>
        
        <category>font</category>
        
        <category>high-dpi</category>
        
        <category>retina</category>
        
      </item>
    
      <item>
        <title>Cut &amp; Paste in the Command Line</title>
        <description>&lt;p&gt;Super short post. This may not be a surprise if you’re an Emacs user, but in my circles people use Vim and we discovered this just today. You can cut &amp;amp; paste in the command line, like this:&lt;/p&gt;

&lt;center&gt;
  &lt;img style=&quot;max-width: 90%; padding: 16px; background-color: black; border-radius: 4px;&quot; class=&quot;noshadow&quot; src=&quot;../../../../assets/video/kill-yank.gif&quot; /&gt;
  &lt;br /&gt;
  &lt;span&gt;&lt;i&gt;Cut to the end of the line with &lt;/i&gt;&lt;code&gt;&lt;b&gt;Ctrl+K&lt;/b&gt;&lt;/code&gt;&lt;i&gt; and paste at the cursor position with &lt;/i&gt;&lt;code&gt;&lt;b&gt;Ctrl+Y&lt;/b&gt;&lt;/code&gt;.
&amp;lt;/center&amp;gt;

There are more options than just **`Ctrl+K`** and **`Ctrl-Y`**. Browse the documentation of Bash and search for *kill* and *yank* which are the terms used there for cut and paste, and the reason why the keys are **K** and **Y**.

I've needed to swap parts of a command line many times in my life and I always found it difficult. I usually combined the GUI selection clipboard with manually deleting a part of the line. I'm glad to have learned this today.
&lt;/span&gt;&lt;/center&gt;
</description>
        <pubDate>Mon, 09 Jan 2017 15:57:58 -0600</pubDate>
        <link>http://www.ateijelo.com/blog/2017/01/09/cut-paste-command-line</link>
        <guid isPermaLink="true">http://www.ateijelo.com/blog/2017/01/09/cut-paste-command-line</guid>
        
        
        <category>bash</category>
        
        <category>shell</category>
        
        <category>cut</category>
        
        <category>paste</category>
        
        <category>emacs</category>
        
      </item>
    
      <item>
        <title>The HooToo Illustration</title>
        <description>&lt;p&gt;My last post got more attention from my friends thanks to the illustration of my HooToo than for the fact that I put OpenVPN inside it. Some doubted I had done it myself, so here’s a little more info.&lt;/p&gt;

&lt;center&gt;
  &lt;img class=&quot;noshadow&quot; src=&quot;../../../../assets/img/hootoo-illustration-4.png&quot; alt=&quot;&quot; /&gt;
&lt;/center&gt;
&lt;p&gt;After I managed to get OpenVPN running I was really excited and I wanted to write a post about it, and I wanted to include an illustration of my HooToo. I took several pictures but I didn’t like any, mostly because the router is worn and because my phone camera is not that great.&lt;/p&gt;

&lt;p&gt;So, seeing that it was almost all geometric shapes or text, I tried to reproduce one of the pictures in Inkscape. I chose this one:&lt;/p&gt;

&lt;center&gt;
  &lt;p&gt;
    &lt;img class=&quot;noshadow&quot; src=&quot;../../../../assets/img/hootoo-illustration-1.jpg&quot; alt=&quot;&quot; /&gt;
  &lt;/p&gt;
&lt;/center&gt;

&lt;p&gt;I imported the image in Inkscape, zoomed-it big and drew lines and curves on top of it, reproducing the shapes I found. I filled it with colors, gradients and some occasional blurring to give it volume. And I added a dark and blurred copy of the basic square shape as shadow. I also left out details that I thought looked bad, like the icons below the Ethernet &amp;amp; USB ports.&lt;/p&gt;

&lt;center&gt;
    &lt;img class=&quot;noshadow&quot; src=&quot;../../../../assets/img/hootoo-illustration-2.png&quot; alt=&quot;&quot; /&gt;
&lt;/center&gt;
&lt;p&gt;I didn’t record the entire process, not having foreseen this post, but here’s an exploded version of the final drawing.&lt;/p&gt;

&lt;center&gt;
  &lt;p&gt;
    &lt;img class=&quot;noshadow&quot; src=&quot;../../../../assets/img/hootoo-illustration-3.png&quot; alt=&quot;&quot; /&gt;
  &lt;/p&gt;
&lt;/center&gt;

&lt;p&gt;Of course, you can check it for yourself, just &lt;a href=&quot;../../../../assets/misc/hootoo-illustration.svg&quot;&gt;get the SVG&lt;/a&gt;.&lt;/p&gt;

</description>
        <pubDate>Sat, 31 Dec 2016 00:18:41 -0600</pubDate>
        <link>http://www.ateijelo.com/blog/2016/12/31/hootoo-illustration</link>
        <guid isPermaLink="true">http://www.ateijelo.com/blog/2016/12/31/hootoo-illustration</guid>
        
        
        <category>hootoo</category>
        
        <category>inkscape</category>
        
      </item>
    
      <item>
        <title>HooToo, OpenWrt, OpenVPN</title>
        <description>&lt;center&gt;
    &lt;p&gt;
      &lt;div style=&quot;display: inline-block; position: relative;&quot;&gt;
      &lt;img style=&quot;&quot; class=&quot;noshadow&quot; src=&quot;../../../../assets/img/hootoo-1.png&quot; alt=&quot;&quot; /&gt;
      &lt;img id=&quot;blue-off&quot; style=&quot;display: none; position: absolute; left: 0; top: 0;&quot; class=&quot;noshadow&quot; src=&quot;../../../../assets/img/hootoo-1-blue-off.png&quot; alt=&quot;&quot; /&gt;
      &lt;/div&gt;
    &lt;/p&gt;
&lt;/center&gt;

&lt;script&gt;
    $(function() {
        var ledoff = $(&quot;img#blue-off&quot;);
        function blink() {
            ledoff.show();
            setTimeout(function() {
                ledoff.hide();
                setTimeout(blink, 1000 + 9000 * Math.random());
            }, 150);
        }
        setTimeout(blink, 5000);
    });
&lt;/script&gt;

&lt;p&gt;Here’s a post for my fellow network ninjas. Yesterday, with some assistance from my networking sensei, Ale Ramos, I managed to install and set up OpenVPN on OpenWrt inside my little HooToo HT-TM02. That’ll be mumbo-jumbo for some people, but if you know what that means, you know it’s a big deal.&lt;/p&gt;

&lt;p&gt;Boy, was I excited when that worked! So much so that I spent last night drawing the HooToo above in Inkscape and I’m quite proud of the result. Looks good, don’t you think? Between that drawing and the VPN I’m feeling renewed love for my handy travel router. It’s like a Christmas present for myself.&lt;/p&gt;

&lt;h3 id=&quot;ok-the-recipe&quot;&gt;Ok, the recipe&lt;/h3&gt;

&lt;p&gt;I won’t extend much. My fellow ninjas (Lu, I’m looking at you) can follow concise instructions. What I’m trying to achieve here is to setup a OpenVPN &lt;strong&gt;client&lt;/strong&gt; connection to my server and then have every wireless station of the HooToo send its internet traffic through that VPN, a common thing used here in Cuba to circumvent internet restrictions (both internal and external).&lt;/p&gt;

&lt;p&gt;These were the steps:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Install OpenWrt inside your HooToo travel router. Get started &lt;a href=&quot;https://wiki.openwrt.org/toh/hootoo/tripmate-nano&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Get your HooToo online and &lt;code class=&quot;highlighter-rouge&quot;&gt;ssh&lt;/code&gt; to it.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Run &lt;code class=&quot;highlighter-rouge&quot;&gt;opkg update&lt;/code&gt; to update the list of packages. In my short experience, this must be done everytime the router restarts, probably to save disk space. For instance, the HT-TM02 has only 4MB in the root partition.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Install &lt;code class=&quot;highlighter-rouge&quot;&gt;openvpn-openssl&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;luci-app-openvpn&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;That second package is a OpenVPN app for LuCi (OpenWrt’s web interface). It looks like this:&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;center&gt;
     &lt;p&gt;&lt;img src=&quot;../../../../assets/img/hootoo-2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
 &lt;/center&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Using that interface, create a new config for your VPN. There you can set up your remote host, the port, the protocol, and your credentials, that is, CA cert, client cert &amp;amp; client key. In this point, you should be already able to start the VPN and ping your remote end from inside your HooToo.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Next is forwarding and NAT’ing&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Go to &lt;em&gt;Network -&amp;gt; Interfaces&lt;/em&gt; and create a new interface. I named mine &lt;code class=&quot;highlighter-rouge&quot;&gt;vpn&lt;/code&gt;. Choose &lt;em&gt;Unmanaged&lt;/em&gt; for the protocol and select &lt;code class=&quot;highlighter-rouge&quot;&gt;tun0&lt;/code&gt; as the covered device. If it’s not there, add it at &lt;em&gt;Custom&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Go to &lt;em&gt;Network -&amp;gt; Firewall&lt;/em&gt; and create a new zone that covers the VPN interface you created in the previous step. Enable masquerading and under &lt;em&gt;Inter-Zone Forwarding&lt;/em&gt; enable forwarding from your WLAN zone, that is the zone of your wireless stations.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That should do it.&lt;/p&gt;

&lt;p&gt;I must confess I had a hard time getting the firewall to work and I ended up opening it too much. You probably don’t want to accept INPUT traffic on your WAN zone (the one that faces the internet), but you need it for the VPN to work. So, either set it to ACCEPT, or leave it ar REJECT and set a specific traffic rule allowing incoming VPN traffic.&lt;/p&gt;

&lt;p&gt;Speak your heart in the comments.&lt;/p&gt;

&lt;h3 id=&quot;the-illustration&quot;&gt;The Illustration&lt;/h3&gt;

&lt;p&gt;The HooToo illustration above has managed to catch the attention of my friends more than having installed OpenVPN in my real HooToo. So, here’s a short follow-up &lt;a href=&quot;../../../../blog/2016/12/31/hootoo-illustration&quot;&gt;post about it&lt;/a&gt;.&lt;/p&gt;

</description>
        <pubDate>Fri, 30 Dec 2016 12:09:23 -0600</pubDate>
        <link>http://www.ateijelo.com/blog/2016/12/30/hootoo-openwrt-openvpn</link>
        <guid isPermaLink="true">http://www.ateijelo.com/blog/2016/12/30/hootoo-openwrt-openvpn</guid>
        
        
        <category>hootoo</category>
        
        <category>wifi</category>
        
        <category>router</category>
        
        <category>openwrt</category>
        
        <category>vpn</category>
        
        <category>openvpn</category>
        
      </item>
    
      <item>
        <title>Odoo Inheritance</title>
        <description>&lt;h2 id=&quot;odoo-inheritance-for-the-uninitiated&quot;&gt;Odoo Inheritance for the uninitiated&lt;/h2&gt;

&lt;p&gt;Complex technology can look like magic. And when you use it long enough,
magic can become second nature, it can become just “the way it works”.
But I don’t like magic when it comes to computers. Specially in a system built with Python, whose &lt;a href=&quot;https://www.python.org/dev/peps/pep-0020/#the-zen-of-python&quot;&gt;Zen&lt;/a&gt; includes &lt;em&gt;Explicit is better than implicit&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I’m barely starting with &lt;a href=&quot;https://www.odoo.com/&quot;&gt;Odoo&lt;/a&gt; (formerly OpenERP) and one of the bits
of magic that struck me most was its inheritance mechanisms. I read the docs,
talked to my senior colleagues and browsed the &lt;a href=&quot;https://github.com/odoo/odoo&quot;&gt;code&lt;/a&gt; heavily. And I wanted to
document my findings, from the point of view of a beginner, before the magic
became “the way it works”.&lt;/p&gt;

&lt;h3 id=&quot;three-inheritance-modes&quot;&gt;Three Inheritance Modes&lt;/h3&gt;

&lt;p&gt;Odoo provides three ways to inherit from and extend existing models. We’ll check
them one by one and, to dispel the magic, we’ll see what’s going on behind the scenes.&lt;/p&gt;

&lt;p&gt;First, let’s see what’s common to all inheritance modes. To define new models you inherit, in the standard Python sense, from Odoo’s &lt;code class=&quot;highlighter-rouge&quot;&gt;models.Model&lt;/code&gt;, like this:&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;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Polygon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Model&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;'shapes.polygon'&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;pos_x&lt;/span&gt; &lt;span class=&quot;o&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;n&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&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;n&quot;&gt;pos_y&lt;/span&gt; &lt;span class=&quot;o&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;n&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Models become tables in Odoo’s database. The &lt;code class=&quot;highlighter-rouge&quot;&gt;_name&lt;/code&gt; attribute is how your model will be identified across Odoo, and it’s where Odoo derives the table name from. After you install a module including the model above, you’ll see the following in pgAdmin:&lt;/p&gt;

&lt;center&gt;
    &lt;p&gt;&lt;img src=&quot;../../../../assets/img/odoo-1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;/center&gt;

&lt;p&gt;Note how &lt;code class=&quot;highlighter-rouge&quot;&gt;pos_x&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;pos_y&lt;/code&gt; appear as columns in a table &lt;code class=&quot;highlighter-rouge&quot;&gt;shapes_polygon&lt;/code&gt; and how Odoo created five extra fields automatically.&lt;/p&gt;

&lt;h3 id=&quot;mode-one-classical-inheritance&quot;&gt;&lt;em&gt;Mode One&lt;/em&gt;: Classical Inheritance&lt;/h3&gt;

&lt;p&gt;The first way to extend a model in Odoo is similar, in spirit, to prototype inheritance in other programming languages. You want to define a &lt;em&gt;new&lt;/em&gt; model, but you want to reuse the fields and methods of an existing model. You achieve that in Odoo like this:&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;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Rectangle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Model&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;'shapes.rectangle'&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;_inherit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'shapes.polygon'&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;o&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;n&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&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;n&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;o&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;n&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The key attribute here is &lt;code class=&quot;highlighter-rouge&quot;&gt;_inherit&lt;/code&gt;. Here you specify the existing model that you want to use as prototype for your new model. Your model gets all the fields of its base model, and it can even use, redefine and access the base methods through &lt;code class=&quot;highlighter-rouge&quot;&gt;super()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With this inheritance, Odoo creates a new table in the database, and includes all the columns of the inherited model. It looks like this in pgAdmin:&lt;/p&gt;

&lt;center&gt;
    &lt;p&gt;&lt;img src=&quot;../../../../assets/img/odoo-2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;/center&gt;

&lt;h3 id=&quot;mode-two-extension&quot;&gt;&lt;em&gt;Mode Two&lt;/em&gt;: Extension&lt;/h3&gt;

&lt;p&gt;In this mode, you don’t create a new model. You want to extend an existing model &lt;em&gt;in place&lt;/em&gt;. This makes it possible to not only add fields and methods, but to redefine existing fields and methods. In this way, your changes may have effect on all current users of the model. This is used very frequently by Odoo’s and third parties’ modules.&lt;/p&gt;

&lt;p&gt;The syntax is actually quite simple: include an &lt;code class=&quot;highlighter-rouge&quot;&gt;_inherit&lt;/code&gt; attribute but &lt;em&gt;omit&lt;/em&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;_name&lt;/code&gt;, like this:&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;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DescriptivePolygon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;models&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;_inherit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'shapes.polygon'&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;o&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;n&quot;&gt;Char&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pos_x&lt;/span&gt; &lt;span class=&quot;o&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;n&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;X&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;default&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;n&quot;&gt;pos_y&lt;/span&gt; &lt;span class=&quot;o&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;n&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Y&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;default&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Sat, 17 Dec 2016 07:36:43 -0600</pubDate>
        <link>http://www.ateijelo.com/blog/2016/12/17/odoo-inheritance</link>
        <guid isPermaLink="true">http://www.ateijelo.com/blog/2016/12/17/odoo-inheritance</guid>
        
        
        <category>openerp</category>
        
        <category>odoo</category>
        
        <category>inheritance</category>
        
        <category>python</category>
        
        <category>postgresql</category>
        
      </item>
    
  </channel>
</rss>
