<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>सतत</title><link>https://baali.muse-amuse.in/</link><description>Documenting my metamorphosis through code, circuits, and containers</description><atom:link href="https://baali.muse-amuse.in/rss.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2026 &lt;a href="mailto:baali@muse-amuse.in"&gt;शांतनु&lt;/a&gt; 
&lt;a rel="license" href="https://creativecommons.org/licenses/by-nc-sa/4.0/"&gt;
&lt;img alt="Creative Commons License BY-NC-SA"
style="border-width:0; margin-bottom:12px;"
src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png"&gt;&lt;/a&gt;</copyright><lastBuildDate>Fri, 06 Feb 2026 10:57:02 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Readable code</title><link>https://baali.muse-amuse.in/posts/readable-code.html</link><dc:creator>शांतनु</dc:creator><description>&lt;div id="outline-container-org2343141" class="outline-2"&gt;
&lt;h2 id="org2343141"&gt;Background&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org2343141"&gt;
&lt;p&gt;
I am revisiting Clojure by &lt;a href="https://github.com/Quartz/bad-data-guide"&gt;cleaning up and handling bad-data&lt;/a&gt;. Data is
in a CSV file. There are two aspects to the problem - return clean
rows and log/find bad ones.
&lt;/p&gt;

&lt;p&gt;
This reminded me of a Clojure project I worked on in 2020 that handled
drop shipping of orders from a third-party website. We would receive
orders in CSV files, create these orders on our store, and respond
with order tracking details in CSV format. Our store API worked with
JSON data, so I had to handle the data transformation from CSV to JSON
and back.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id="outline-container-orgc18c57b" class="outline-2"&gt;
&lt;h2 id="orgc18c57b"&gt;Problem: Handle the transition of data from flat to nested form&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-orgc18c57b"&gt;
&lt;p&gt;
I was learning Clojure while working on that project, and I wrote the
following function to flatten nested order data:
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;defn &lt;/span&gt;&lt;span class="nv"&gt;single-row-per-sku&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s"&gt;"Convert consolidated processed orders to rows containing each SKU"&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;reduce &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;order&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;concat &lt;/span&gt;&lt;span class="nv"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;map &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;merge &lt;/span&gt;&lt;span class="nv"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dissoc &lt;/span&gt;&lt;span class="nv"&gt;order&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:items&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:items&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;order&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
It works—I wrote unit tests to make sure it did. But it is dense and
&lt;span style="color: red;"&gt;unreadable&lt;/span&gt;. I can't
even recall how I explained this section during code review.
&lt;/p&gt;

&lt;p&gt;
I used &lt;a href="https://www.braveclojure.com/introduction/"&gt;Clojure for the Brave and True&lt;/a&gt; for learning the language. It
was a fun and refreshing read on introducing core concepts. The
function that I wrote doesn't do justice to the quality of the
content.
&lt;/p&gt;

&lt;p&gt;
Brave Clojure also has this relevant quote from &lt;a href="https://www.braveclojure.com/do-things/"&gt;Alan Perlis&lt;/a&gt;:
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
It is better to have 100 functions operate on one data structure than
10 functions on 10 data structures.
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
I came from Python background. I also didn't know about &lt;a href="https://clojure.org/guides/threading_macros"&gt;threading
macros&lt;/a&gt; in Clojure when I wrote above function. The quote really made
sense to me once I &lt;a href="https://baali.muse-amuse.in/posts/clojure-keeping-the-code-readable.html"&gt;learned&lt;/a&gt; about threading.
&lt;/p&gt;

&lt;p&gt;
As I am revising Clojure concepts I am writing a lot of small function
and testing them using the &lt;a href="https://clojure.org/guides/repl/introduction"&gt;REPL&lt;/a&gt;. In the same vein I feel following is
more readable equivalent:
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;defn &lt;/span&gt;&lt;span class="nv"&gt;get-address&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;order&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dissoc &lt;/span&gt;&lt;span class="nv"&gt;order&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:items&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;defn &lt;/span&gt;&lt;span class="nv"&gt;get-items&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;order&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;order&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:items&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;defn &lt;/span&gt;&lt;span class="nv"&gt;flatten-items&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;order&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;address&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get-address&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;items&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get-items&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;items&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;map &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;merge &lt;/span&gt;&lt;span class="nv"&gt;address&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;%&lt;/span&gt;&lt;span class="p"&gt;)))))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;defn &lt;/span&gt;&lt;span class="nv"&gt;single-row-per-sku&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;orders&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;map &lt;/span&gt;&lt;span class="nv"&gt;flatten-items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nv"&gt;flatten&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
Small functions. Threading macros. Names that make sense. Easy to read
and functional. I don't think it's the final version-the &lt;a href="https://web.archive.org/web/20190112093304/http://people.cs.uchicago.edu/~wiseman/humor/large-programs.html"&gt;ballad&lt;/a&gt;
continues as I keep learning.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description><category>clojure</category><category>discipline</category><category>etl</category><category>learning</category><category>python</category><category>tools</category><guid>https://baali.muse-amuse.in/posts/readable-code.html</guid><pubDate>Fri, 30 Jan 2026 09:22:20 GMT</pubDate></item><item><title>Getting started with powerful abstract tools: Emacs, Vim</title><link>https://baali.muse-amuse.in/posts/powerful-tools-emacs-vim-et-al.html</link><dc:creator>शांतनु</dc:creator><description>&lt;div id="outline-container-orga187f93" class="outline-2"&gt;
&lt;h2 id="orga187f93"&gt;Foundation: Text Editors&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-orga187f93"&gt;
&lt;p&gt;
In his book The Dip, Seth Godin talks about snowboarding:
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
Snowboarding is a hip sport. It’s fast, exciting and reasonably
priced; and it makes you look very cool. So why are there so few
snowboarders? Because learning the basic skills constitutes a
painful Dip. It takes a few days to get the hang of it, and,
during those few days, you’ll get pretty banged up. It’s easier to
quit than it is to keep going.
&lt;/p&gt;

&lt;p&gt;
The brave thing to do is to tough it out and end up on the other
side–getting all the benefits that come from scarcity. The mature
thing to do is not even to bother starting to snowboard because you’re
probably not going to make it through the Dip. And the stupid thing to
do is to start, give it your best shot, waste a lot of time and money,
and quit right in the middle of the Dip.
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
In the programming world, editors are an important basic skill-they
are like the snowboard in this analogy. I would often read about vim
and emacs. In college, I tried them a couple of times and got
&lt;a href="https://stackoverflow.com/questions/11828270/how-do-i-exit-vim"&gt;stuck&lt;/a&gt;. &lt;code&gt;vim&lt;/code&gt;'s swap file prompt was scary. When &lt;code&gt;git&lt;/code&gt; opened vim's
side-by-side buffer to resolve merge conflicts, I would start
sweating.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id="outline-container-orga343144" class="outline-2"&gt;
&lt;h2 id="orga343144"&gt;Finding the Spark&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-orga343144"&gt;
&lt;p&gt;
Both &lt;a href="https://www.vim.org/"&gt;&lt;code&gt;VIM&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://www.gnu.org/software/emacs/"&gt;&lt;code&gt;Emacs&lt;/code&gt;&lt;/a&gt; are powerful and ubiquitous text editors and
both are infamous for their steep learning curves. On my own, picking
up such a tool was intimidating and frustrating. Here is what did the
trick for me: watch a power user use them. It really hits you when
this happens in person. I saw someone using org-mode in &lt;code&gt;emacs&lt;/code&gt;, its
table editor, exporting it in Markdown, HTML, and PDF, and then he
used it to create a presentation using &lt;a href="https://github.com/yjwen/org-reveal"&gt;org-reveal&lt;/a&gt;, I was blown away
🤯. Later another friend of mine was using &lt;code&gt;emacs&lt;/code&gt; and &lt;a href="https://www.gnu.org/software/tramp/"&gt;&lt;code&gt;tramp&lt;/code&gt;&lt;/a&gt; to make
code adjustments on a live server (avoid doing that) 🫡. During
another pairing session, my colleague was using &lt;code&gt;vim&lt;/code&gt;, navigating
code, renaming variables with visual mode, and running macros-it was
magic 🤹🏽. These moments made these editors cool for me-simple yet
very pliable and that gave me enough escape velocity to push through
the steep learning curve.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id="outline-container-orga4fc1eb" class="outline-2"&gt;
&lt;h2 id="orga4fc1eb"&gt;The Learning Curve&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-orga4fc1eb"&gt;
&lt;p&gt;
These editors are abstract tools that carry certain labels: "hard",
"for smart people only", "set in their own ways". I struggled with two
things when trying to pick them up. When I was working on a problem, I
didn't want to get distracted by my editor, its mode, buffers, opening
and closing etc. Second, I didn't consider myself smart and I kept my
distance (thinking I was being mature) from tools that carried that
impression.
&lt;/p&gt;

&lt;p&gt;
But once I realized editors were a fundamental skill, I realized I
should invest the time, don't make it (the editor) the last thing. I
kept retrying, just like how I would approach a boss fight in a
game. I didn't scare that easy in the next round, I noticed patterns,
found my corner, got comfortable and started attacking. It grew on
me. I acquired the taste. The same approach works for all
crafts. Later, as I worked on new problem, these editors didn't get in
the way-they provided the structure that will helped me focus.
&lt;/p&gt;

&lt;p&gt;
I was lucky to work with such power users, and they allowed me the
space to ask stupid questions. I still nag them about their setup when
we meet in person. I use &lt;code&gt;Emacs&lt;/code&gt;. I can't program without org-mode,
magit, tramp et al. I am slowly working my way through its LSP support
and configuring and tweaking things, one language at a time. I've
tried other editors, I kept looking for these features and so far my
attempts to install plugins/addons haven't worked. I keep returning to
&lt;code&gt;Emacs&lt;/code&gt;. As the landscape evolves with AI agents and MCP, I will
explore whether I can integrate them with &lt;code&gt;Emacs&lt;/code&gt; or if I'll need to
adopt a more contemporary editor.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description><category>emacs</category><category>tools</category><guid>https://baali.muse-amuse.in/posts/powerful-tools-emacs-vim-et-al.html</guid><pubDate>Tue, 13 Jan 2026 15:35:00 GMT</pubDate></item><item><title>One Firmware for all ESP32 Variants: Solving Pin Mapping Pain</title><link>https://baali.muse-amuse.in/posts/untangle-the-wires.html</link><dc:creator>शांतनु</dc:creator><description>&lt;p&gt;
For my embedded project, I needed &lt;a href="https://www.nxp.com/docs/en/nxp/data-sheets/PN532_C1.pdf"&gt;NFC card&lt;/a&gt; functionality for WiFi
onboarding and user interactions. When integrating NFC functionality
into ESP32 projects, pin mapping became a major pain point as I was
working with different ESP32 boards.
&lt;/p&gt;

&lt;p&gt;
&lt;a href="https://github.com/adafruit/Adafruit-PN532/blob/master/examples/ntag2xx_read/ntag2xx_read.ino"&gt;Adafruit's arduino library example&lt;/a&gt; sets up the NFC reader in
following manner:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;lt;Wire.h&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// Using the SPI breakout, define the pins for SPI communication.&lt;/span&gt;
&lt;span class="cp"&gt;#define PN532_SCK  (2)&lt;/span&gt;
&lt;span class="cp"&gt;#define PN532_MOSI (3)&lt;/span&gt;
&lt;span class="cp"&gt;#define PN532_SS   (4)&lt;/span&gt;
&lt;span class="cp"&gt;#define PN532_MISO (5)&lt;/span&gt;
&lt;span class="n"&gt;Adafruit_PN532&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;nfc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PN532_SCK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PN532_MISO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PN532_MOSI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PN532_SS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
These pins are placeholders and they would vary for each ESP32 variant
and I had several: &lt;a href="https://randomnerdtutorials.com/esp32-pinout-reference-gpios/"&gt;ESP-WROOM-32&lt;/a&gt;, &lt;a href="https://randomnerdtutorials.com/getting-started-esp32-c3-super-mini/"&gt;ESP32-C3 Super Mini&lt;/a&gt;, &lt;a href="https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32s3/esp32-s3-devkitc-1/user_guide_v1.1.html#hardware-reference"&gt;S3&lt;/a&gt;, &lt;a href="https://wiki.seeedstudio.com/xiao_esp32s3_getting_started/"&gt;XIAO ESP32S3&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
I tested the reader across all these variants, different modes: &lt;code&gt;SPI&lt;/code&gt;,
&lt;code&gt;I2C&lt;/code&gt;, wiring and reading different NFC cards.
&lt;/p&gt;

&lt;p&gt;
First challenge was to figure out the mapping of pins. I found that
&lt;a href="https://github.com/espressif/arduino-esp32/tree/master/variants"&gt;espressif's arduino support&lt;/a&gt; is the best resource for it. For each
board the file &lt;a href="https://github.com/espressif/arduino-esp32/blob/master/variants/uPesy_esp32c3_mini/pins_arduino.h"&gt;&lt;code&gt;pins_arduino.h&lt;/code&gt;&lt;/a&gt; gives us the right pins. For the
&lt;a href="https://randomnerdtutorials.com/getting-started-esp32-c3-super-mini/"&gt;ESP32-C3 Super Mini&lt;/a&gt; board, the above example NFC reader code would
become:
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;lt;Wire.h&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;#define PN532_SCK  (4)&lt;/span&gt;
&lt;span class="cp"&gt;#define PN532_MOSI (6)&lt;/span&gt;
&lt;span class="cp"&gt;#define PN532_SS   (7)&lt;/span&gt;
&lt;span class="cp"&gt;#define PN532_MISO (5)&lt;/span&gt;
&lt;span class="n"&gt;Adafruit_PN532&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;nfc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PN532_SCK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PN532_MISO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PN532_MOSI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PN532_SS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
But as I iterated through these ESP32 variants it became quite a pain
adjusting those pins in the firmware and flashing it. Eventually I
realized what would simplify this: I could have a single firmware that
will work with everything:
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;lt;Wire.h&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;Adafruit_PN532&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;nfc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SCK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MISO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MOSI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
These pins, &lt;code&gt;SCK&lt;/code&gt;, &lt;code&gt;MISO&lt;/code&gt; are just like another constant:
&lt;a href="https://docs.arduino.cc/language-reference/en/variables/constants/ledbuiltin/"&gt;&lt;code&gt;LED_BUILTIN&lt;/code&gt;&lt;/a&gt;, each Arduino &lt;a href="https://baali.muse-amuse.in/posts/esp32-zephyr-and-blinky.html"&gt;board&lt;/a&gt; that doesn't use default pin &lt;code&gt;13&lt;/code&gt;,
defines it in their &lt;code&gt;pins_arduino.h&lt;/code&gt; header. Similarly all the
variants have their own respective &lt;code&gt;pins_arduino.h&lt;/code&gt; file with right
pins. As I select the board inside Arduino IDE, these variables are
always available. Further this pattern isn't limited to NFC readers,
all the SPI peripheral using those pins would work.
&lt;/p&gt;</description><category>arduino</category><category>diy</category><category>embedded</category><category>esp32</category><category>esp-idf</category><category>FOSS</category><category>iot</category><category>zephyr</category><guid>https://baali.muse-amuse.in/posts/untangle-the-wires.html</guid><pubDate>Sat, 16 Aug 2025 05:07:10 GMT</pubDate></item><item><title>CPR for a Docker container</title><link>https://baali.muse-amuse.in/posts/cpr-for-a-docker-container.html</link><dc:creator>शांतनु</dc:creator><description>&lt;div id="outline-container-org7289c63" class="outline-2"&gt;
&lt;h2 id="org7289c63"&gt;Background&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org7289c63"&gt;
&lt;p&gt;
Picture this: You're experimenting with a Docker container, enable a
feature, and suddenly your container is stuck in an endless restart
loop. In a panic, you run &lt;code&gt;docker compose down&lt;/code&gt; and watch everything
disappear.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id="outline-container-orgf3c53f0" class="outline-2"&gt;
&lt;h2 id="orgf3c53f0"&gt;What You Should Do Instead&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-orgf3c53f0"&gt;
&lt;p&gt;
&lt;b&gt;&lt;b&gt;Don't lose the container&lt;/b&gt;&lt;/b&gt;, no matter how broken it is. Create a new
image from the container using &lt;code&gt;docker&lt;/code&gt; commit: &lt;code&gt;docker commit
&amp;lt;container-id&amp;gt; broken-image&lt;/code&gt; (you get container id using &lt;code&gt;docker ps
-a&lt;/code&gt; command)
&lt;/p&gt;

&lt;p&gt;
From here there are a couple of things you could do. I was using
&lt;code&gt;Dockerfile&lt;/code&gt; to build and setup things. Modify it to use broken image
as base and install the missing dependencies:
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;FROM broken-image:latest
RUN pip install &amp;lt;package-name&amp;gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
And with this in place I can restart the &lt;code&gt;docker compose&lt;/code&gt; stack.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id="outline-container-org763f826" class="outline-2"&gt;
&lt;h2 id="org763f826"&gt;Complicated changes&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org763f826"&gt;
&lt;p&gt;
In case damage to your container is more severe there will be
additional steps to revive the container.
&lt;/p&gt;
&lt;ol class="org-ol"&gt;
&lt;li&gt;Create image from your broken container: &lt;code&gt;docker commit &amp;lt;container-id&amp;gt; broken-image&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Create a new container from this broken image with a different
&lt;code&gt;entrypoint&lt;/code&gt; command (default command would restart the broken stack):
&lt;code&gt;docker run -it --entrypoint=/bin/bash broken-image:latest&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Adjust or remove your changes, install missing dependencies, run
migrations, what have you&lt;/li&gt;
&lt;li&gt;Create a new image from this container that has all the fixes:
&lt;code&gt;docker commit &amp;lt;container-id-with-bash-running&amp;gt; fixed-image&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;
Start a new container using this &lt;code&gt;fixed-image&lt;/code&gt; and default command
that brings up your original stack. In my case I removed &lt;code&gt;build&lt;/code&gt;
step from my &lt;code&gt;docker-compose.yml&lt;/code&gt; file and pointed it to the new
image:
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;   app:
     image: fixed-image:latest
&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;Be careful with running faulty containers. I was really confused
balancing &lt;code&gt;docker compose&lt;/code&gt; commands and direct &lt;code&gt;docker&lt;/code&gt; commands. I
noticed that &lt;code&gt;docker compose&lt;/code&gt; (re)start command would also (re)start
all broken/existing containers and I had to manually remove them to
be able to get the complete stack running again.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
With this approach I was no longer building a new Docker
image. Instead I used &lt;code&gt;docker compose&lt;/code&gt; to start container using
&lt;code&gt;fixed-image&lt;/code&gt; and default command.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id="outline-container-org92dbe5b" class="outline-2"&gt;
&lt;h2 id="org92dbe5b"&gt;Summary:&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org92dbe5b"&gt;
&lt;ul class="org-ul"&gt;
&lt;li&gt;Always test changes in development first&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;docker commit&lt;/code&gt; with your container before making risky changes&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;</description><category>debugging</category><category>docker</category><category>tools</category><guid>https://baali.muse-amuse.in/posts/cpr-for-a-docker-container.html</guid><pubDate>Sat, 14 Jun 2025 10:35:55 GMT</pubDate></item><item><title>The right recipe</title><link>https://baali.muse-amuse.in/posts/the-right-recipe.html</link><dc:creator>शांतनु</dc:creator><description>&lt;p&gt;
A colleague reached out to me for a pairing session on his &lt;a href="https://www.carbon2h.com/"&gt;project&lt;/a&gt;. I
explained upfront that my hourly rate far exceeds most LLM
subscription costs. He understood — while LLMs have their place, he
needed help clarifying requirements and making real progress.
&lt;/p&gt;

&lt;p&gt;
His existing setup: several machines pushing data to cloud, a &lt;a href="https://lookerstudio.google.com/gallery"&gt;looker
studio dashboard&lt;/a&gt; connected to a placeholder google spreadsheet. To
start, he wanted to make this dashboard live.
&lt;/p&gt;

&lt;p&gt;
His requirements:
&lt;/p&gt;
&lt;ol class="org-ol"&gt;
&lt;li&gt;A live dashboard&lt;/li&gt;
&lt;li&gt;Python based: his comfort zone&lt;/li&gt;
&lt;li&gt;Daily data pulls: sufficient for non-temporal data&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
The solution was obvious, I have used it &lt;a href="https://github.com/baali/nps-d"&gt;before&lt;/a&gt;: A GitHub action that
runs daily, pulls cloud data and updates his spreadsheet — instantly
making his dashboard live. I understand that I am contributing to the
Github actions phenomena:
&lt;/p&gt;


&lt;div id="org889fe46" class="figure"&gt;
&lt;p&gt;&lt;img src="https://baali.muse-amuse.in/galleries/actions.jpg" alt="nil"&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
The trickiest parts? Wrestling with Google's Sheets API authentication
and configuring GitHub &lt;a href="https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions#using-secrets-in-a-workflow"&gt;secrets&lt;/a&gt; properly. But once those pieces
clicked, everything flowed. Four one hour focused pairing sessions,
that's it. He got a working solution plus he understood all the moving
parts to continue experimenting on his own.
&lt;/p&gt;

&lt;p&gt;
Four hours, serverless, an elegant solution. This is what going back
to first principles looks like.
&lt;/p&gt;</description><category>project</category><category>python</category><category>tools</category><guid>https://baali.muse-amuse.in/posts/the-right-recipe.html</guid><pubDate>Fri, 30 May 2025 08:03:09 GMT</pubDate></item><item><title>Setting Up Zephyr for ESP32: A Blinky LED Journey</title><link>https://baali.muse-amuse.in/posts/esp32-zephyr-and-blinky.html</link><dc:creator>शांतनु</dc:creator><description>&lt;p&gt;
I recently started working with a client on an &lt;a href="https://docs.zephyrproject.org/latest/boards/espressif/esp32_devkitc_wroom/doc/index.html"&gt;ESP32&lt;/a&gt; based
project. Having prior experience with Zephyr on Nordic boards, I
decided to leverage Zephyr's Espressif support for this project. While
the documentation mentions the classic "blinky" example, I noticed it
lacked the necessary device overlay file for my specific board.
&lt;/p&gt;

&lt;div id="outline-container-org1a9d33e" class="outline-2"&gt;
&lt;h2 id="org1a9d33e"&gt;Finding the Right Example&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org1a9d33e"&gt;
&lt;p&gt;
Fortunately, I discovered that the &lt;a href="https://docs.zephyrproject.org/latest/samples/basic/blinky_pwm/README.html"&gt;"PWM Blinky"&lt;/a&gt; example included
sample overlay files I could reference. After compiling the example, I
encountered this error when attempting to flash the device:
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;([Errno 5] could not open port /dev/ttyUSB0: [Errno 5] Input/output error: '/dev/ttyUSB0')
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
Running stat &lt;code&gt;/dev/ttyUSB0&lt;/code&gt; revealed that the device belonged to the
&lt;code&gt;dialout&lt;/code&gt; group. I fixed the permission issue by adding my user to
this group:
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;sudo usermod -a -G dialout $USER
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
After rebooting to apply the new permissions, &lt;code&gt;west flash&lt;/code&gt; worked perfectly.
&lt;/p&gt;
&lt;/div&gt;

&lt;div id="outline-container-orgb5ee3da" class="outline-3"&gt;
&lt;h3 id="orgb5ee3da"&gt;Creating the missing overlay file&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-orgb5ee3da"&gt;
&lt;p&gt;
The basic &lt;a href="https://docs.zephyrproject.org/latest/samples/basic/blinky/README.html"&gt;Blinky&lt;/a&gt; documentation explains the need for an overlay file
that points to the correct GPIO pin. Based on the PWM Blinky example,
I discovered my board (&lt;code&gt;esp32_devkitc_wroom&lt;/code&gt;) has an onboard blue LED
connected to &lt;code&gt;pwm_led_gpio0_2&lt;/code&gt;. I created following overlay file:
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;/ {
    aliases {
        led0 = &amp;amp;myled0;
    };
    leds {
        compatible = "gpio-leds";
        myled0: led_0 {
            gpios = &amp;lt;&amp;amp;gpio0 2 GPIO_ACTIVE_LOW&amp;gt;;
        };
    };
};
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id="outline-container-orgd907882" class="outline-3"&gt;
&lt;h3 id="orgd907882"&gt;Success&lt;/h3&gt;
&lt;div class="outline-text-3" id="text-orgd907882"&gt;
&lt;p&gt;
With the overlay in place(&lt;code&gt;samples/basic/blinky/boards/esp32_devkitc_wroom_procpu.overlay&lt;/code&gt;),
I compiled the project and it worked:
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;west build -p always -b esp32_devkitc_wroom/esp32/procpu samples/basic/blinky
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
After flashing the board, there it was, blinking blue LED - a small
victory that is still the first step and I keep revisiting it.
&lt;/p&gt;

&lt;p&gt;
Next up: implementing the project's actual functionality, including
WiFi provisioning, ePaper display integration, and LED ring controls.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description><category>arduino</category><category>esp32</category><category>iot</category><category>zephyr</category><guid>https://baali.muse-amuse.in/posts/esp32-zephyr-and-blinky.html</guid><pubDate>Tue, 08 Apr 2025 11:49:10 GMT</pubDate></item><item><title>Resolution / सलटारा </title><link>https://baali.muse-amuse.in/posts/resolution.html</link><dc:creator>शांतनु</dc:creator><description>&lt;p&gt;
Continuing from the &lt;a href="https://baali.muse-amuse.in/posts/assumptions.html"&gt;last post&lt;/a&gt;. The fact that Python interpreter didn't
catch the regex pattern in tests but threw &lt;code&gt;compile&lt;/code&gt; error on staging
environment was very unsettling. Personally I knew that I am missing
something on my part and I was very reluctant on blaming the language
itself. Turns out, I was correct 🙈.
&lt;/p&gt;


&lt;p&gt;
I was looking for early feedback and comments on the post and &lt;a href="https://github.com/punchagan"&gt;Punch&lt;/a&gt;
was totally miffed by this inconsistency and specially the conclusion
I was coming to
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
Umm, I'm not sure I'm happy with the suggestion that I should check
every regex I write, with an external website tool to make sure the
regex itself is a valid one. "Python interpreter ka kaam main karoon
abhi?" :frown:
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
He quickly compared the behavior between JS(compiler complianed) and
Python(did nothing). Now that I had full attention from him there was
no more revisiting this at some later stage. We started digging. He
confirmed that the regex failed with &lt;code&gt;Python2&lt;/code&gt; but not with
&lt;code&gt;Python3.11&lt;/code&gt; with a simple command
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;docker run -it python:3.11 python -c 'import re; p = r"\s*+"; re.compile(p); print("yo")'
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
I followed up on this and that was the mistake on my part. My local
python setup was &lt;code&gt;3.11&lt;/code&gt;, I was using this to run my tests and staging
environment was using &lt;code&gt;3.10&lt;/code&gt;. When I ran my tests within containerized
setup, similar to what we used on staging, Python interpreter rightly
caught faulty regex:
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;re.error: multiple repeat at position 11
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
Something changed between python &lt;code&gt;3.11&lt;/code&gt; and &lt;code&gt;3.10&lt;/code&gt; release. I looked
at the &lt;a href="https://www.python.org/downloads/release/python-3110/"&gt;release logs&lt;/a&gt; and noticed this new feature &lt;a href="https://github.com/python/cpython/pull/31982"&gt;atomic grouping&lt;/a&gt; and
possessive quantifier. I am not sure how to use it or what it does
&lt;a href="https://learnbyexample.github.io/python-regex-possessive-quantifier/"&gt;1&lt;/a&gt;. But with this feature, python &lt;code&gt;3.11&lt;/code&gt; regex pattern: &lt;code&gt;r"\s*+"&lt;/code&gt; is a
valid one. I was using this to run tests locally. On staging we had
python &lt;code&gt;3.10&lt;/code&gt;, and with it interpreter threw an error.
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;Lesson learned&lt;/b&gt;:
&lt;/p&gt;

&lt;p&gt;
I was testing things by running things locally. Don't do that. Setup a
stack and get is as close to the staging and production as
possible. And always, always run tests within it.
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
You pull an end of a mingled yarn,
&lt;/p&gt;

&lt;p&gt;
to sort it out,
&lt;/p&gt;

&lt;p&gt;
looking for a resolution but there is none,
&lt;/p&gt;

&lt;p&gt;
it is just layers and layers.
&lt;/p&gt;
&lt;/blockquote&gt;</description><category>docker</category><category>learning</category><category>python</category><category>regex</category><category>tests</category><guid>https://baali.muse-amuse.in/posts/resolution.html</guid><pubDate>Fri, 08 Mar 2024 10:11:47 GMT</pubDate></item><item><title>Assumptions / घारणा</title><link>https://baali.muse-amuse.in/posts/assumptions.html</link><dc:creator>शांतनु</dc:creator><description>&lt;p&gt;
In the team I started working with recently, I am advocating for code
reviews, best practices, tests and using CI/CD. I feel in Python
ecosystem it is hard to push reliable code without these practices.
&lt;/p&gt;

&lt;p&gt;
I was assigned an issue to find features from text and had to extract
money figures. I started searching for existing libraries (&lt;a href="https://github.com/python-humanize/humanize"&gt;humanize&lt;/a&gt;,
&lt;a href="https://spacy.io/usage/linguistic-features#named-entities"&gt;spacy&lt;/a&gt;, &lt;a href="https://pypi.org/project/numerize/"&gt;numerize&lt;/a&gt;, &lt;a href="https://advertools.readthedocs.io/en/master/advertools.extract.html#extract-currency"&gt;advertools&lt;/a&gt;, &lt;a href="https://pypi.org/project/price-parser/"&gt;price-parser&lt;/a&gt;). These libraries always hit
an edge case with my requirements. I drafted an OpenAI prompt and got
a decent regex pattern that covered most of my requirements. I made a
few improvements to the pattern and wrote unit and integration tests
to confirm that the logic was covering everything I wanted. So far so
good. I got the PR approved, merged and deployed. Only to find that
the code didn't work and it was breaking on staging environment.
&lt;/p&gt;

&lt;p&gt;
As the prevailing wisdom goes &lt;a href="https://blog.codinghorror.com/regular-expressions-now-you-have-two-problems/"&gt;around regular expressions based on 1997
chestnut&lt;/a&gt;
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
Some people, when confronted with a problem, think "I know, I'll use
regular expressions." Now they have two problems.
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
I have avoided regular expressions, and here I am.
&lt;/p&gt;

&lt;p&gt;
I was getting following stacktrace:
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;"/lib/number_parser.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;extract_numbers&lt;/span&gt;
&lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"|"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;monetary_patterns&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;"/usr/local/lib/python3.10/re.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;251&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;compile&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;"/usr/local/lib/python3.10/re.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;303&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_compile&lt;/span&gt;
&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sre_compile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;"/usr/local/lib/python3.10/sre_compile.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;788&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;compile&lt;/span&gt;
&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sre_parse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;"/usr/local/lib/python3.10/sre_parse.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;955&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt;
&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_parse_sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;SRE_FLAG_VERBOSE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;"/usr/local/lib/python3.10/sre_parse.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;444&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_parse_sub&lt;/span&gt;
&lt;span class="n"&gt;itemsappend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nested&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;"/usr/local/lib/python3.10/sre_parse.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;672&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_parse&lt;/span&gt;
&lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"multiple repeat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;	
&lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;multiple&lt;/span&gt; &lt;span class="n"&gt;repeat&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;
Very confusing. &lt;a href="https://stackoverflow.com/questions/19942314/python-multiple-repeat-error"&gt;Seems&lt;/a&gt; there was an issue with my regex pattern. But
the logic worked, I tested it. The pattern would fail for a certain
type of input and work for others. What gives? I shared the regex
pattern with a colleague and he promptly identified the issue, there
was a redundant &lt;code&gt;+&lt;/code&gt; in my pattern. I wanted to look for empty spaces
and I had used a wrong pattern &lt;code&gt;r'\s*+'&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
I understand that Python is a &lt;a href="https://python.swaroopch.com/about_python.html"&gt;&lt;b&gt;&lt;b&gt;interpreted&lt;/b&gt;&lt;/b&gt; and &lt;b&gt;&lt;b&gt;dynamically&lt;/b&gt;&lt;/b&gt;
typed&lt;/a&gt; and that's why I wrote those tests(unit AND integration),
containerized the application to &lt;a href="https://baali.muse-amuse.in/posts/striking-a-balance-between-clobbering-and-learning.html"&gt;avoid&lt;/a&gt; the &lt;a href="https://github.com/cosmologicon/pywat"&gt;wat&lt;/a&gt;. And here I was,
despite all the measures, preaching best practices and still facing
such a bug for the first time. I &lt;b&gt;&lt;b&gt;assumed&lt;/b&gt;&lt;/b&gt; that interpreter will do
its job and complain about the buggy regex pattern and my tests would
fail. Thanks to &lt;a href="https://github.com/punchagan"&gt;Punch&lt;/a&gt; we further dug into this behavior &lt;a href="https://baali.muse-amuse.in/posts/resolution.html"&gt;here&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
A friend of mine, &lt;a href="https://tcluri.github.io/"&gt;Tejaa&lt;/a&gt; had shared a regex resource:
&lt;a href="https://regex-vis.com/"&gt;https://regex-vis.com/&lt;/a&gt;, it is a visual representation (&lt;a href="https://en.wikipedia.org/wiki/State_diagram"&gt;state diagram
of sorts&lt;/a&gt;) of the grammar. I tested my faulty regex pattern with &lt;code&gt;\s*+&lt;/code&gt;
and the site reported: &lt;code&gt;Error: nothing to repeat&lt;/code&gt;. This is better,
error is similar with what I was noticing in my stack trace. I also
tested the fixed pattern and the site showed a correct representation
of what I wanted.
&lt;/p&gt;

&lt;p&gt;
Always confirm your assumptions.
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
assumption is the mother of all mistakes (fuckups)
&lt;/p&gt;
&lt;/blockquote&gt;</description><category>learning</category><category>python</category><category>regex</category><category>tests</category><guid>https://baali.muse-amuse.in/posts/assumptions.html</guid><pubDate>Fri, 01 Mar 2024 10:09:24 GMT</pubDate></item><item><title>Pragmatic Zen of Python</title><link>https://baali.muse-amuse.in/posts/pragmatic-zen-of-python.html</link><dc:creator>शांतनु</dc:creator><description>&lt;p&gt;
I gave a &lt;a href="https://muse-amuse.in/~baali/pragmatic.html"&gt;talk&lt;/a&gt; at &lt;a href="https://conference.pydelhi.org/"&gt;PyDelhi&lt;/a&gt; 2023 and got good feedback from the
participants. It was a nice opportunity to meet lots of community
member after a long time. These in person exchange of ideas and
conversations are very essential for personal growth and learning. I
will continue to do more in 2024 🤞🏾
&lt;/p&gt;</description><category>learning</category><category>python</category><category>tests</category><guid>https://baali.muse-amuse.in/posts/pragmatic-zen-of-python.html</guid><pubDate>Sat, 19 Aug 2023 06:57:14 GMT</pubDate></item><item><title>2022....</title><link>https://baali.muse-amuse.in/posts/2022.html</link><dc:creator>शांतनु</dc:creator><description>&lt;p&gt;
Here is a wishlist for 2022. I have made similar lists in past, but
privately. I didn't do well on following up on them. I want to change
that. I will keep the list small and try to make them specific.
&lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;&lt;p&gt;
Read More
&lt;/p&gt;

&lt;p&gt;
I didn't read much in 2021. I have three books right now with me:
Selfish Gene by Richard dawkins, Snow Crash by Neal Stephenson,
Release It!  by Michael T. Nygard. I want to finish them. And
possibly add couple more to this list. Last year, I got good
feedback on how to improve and grow as a programmer. Keeping that in
mind I will pick up some/a technical book. I have never tried
before. Lets see how that goes.
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Monitoring air quality data of Bikaner
&lt;/p&gt;

&lt;p&gt;
When I was in Delhi back in 2014 I was really miffed by
deteriorating air quality in Delhi. There was a number attached to
it, AQI, it was registered by sensors in different locations. I felt
it didn't reflect the real number of air quality for commuters like
me. I would daily commute from office on foot and I would see lot of
other folks stuck in traffic breathing in the same pollution. I
tried to do something back then, didn't get too much momentum and
stopped.
&lt;/p&gt;

&lt;p&gt;
Recently with help of Shiv I am mentally getting ready to pick it
up, again. In Bikaner we don't have official, public AQI number (&lt;a href="https://www.iqair.com/in-en/india/rajasthan/bikaner"&gt;1&lt;/a&gt;,
&lt;a href="https://www.aqi.in/dashboard/india/rajasthan/bikaner"&gt;2&lt;/a&gt;, &lt;a href="https://baali.muse-amuse.in/galleries/AQI_Rajasthan.pdf"&gt;3&lt;/a&gt;). I would like that to change. I want to start small, couple of
boxes that could start collecting data. And add more features to it
and increase the fleet to cover more areas in the City.
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Write More:
&lt;/p&gt;

&lt;p&gt;
I was really bad with writing things in 2021. Fix it. I want to
write 4 to 5 good, thought out, well written posts. I also have lot
of drafts, I want to finish writing them. I think being more
consistent with writing club on wednesdays would be helpful.
&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;
Personal Archiving:
&lt;/p&gt;

&lt;p&gt;
Again a long time simmering project. I want to put together
scaffolding that can hold this. I recently read this &lt;a href="https://cprimozic.net/blog/my-selfhosted-websites-architecture/"&gt;post&lt;/a&gt;, the
author talks about different services he runs on his server. I am
getting a bit familiar with containers, &lt;code&gt;docker-compose&lt;/code&gt;,
ansible. And this post has given me some new inspirations on taking
some small steps. I think the target around this project are still
vague and not specific. I want some room here. To experiment, get
comfortable, try existing tools.
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;</description><category>discipline</category><category>diy</category><category>education</category><category>writing</category><guid>https://baali.muse-amuse.in/posts/2022.html</guid><pubDate>Fri, 31 Dec 2021 18:07:55 GMT</pubDate></item></channel></rss>