<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>sandeepk</title>
    <link>https://blogs.dgplug.org/sandeepk/</link>
    <description></description>
    <pubDate>Fri, 10 Apr 2026 14:43:38 +0000</pubDate>
    <item>
      <title>Git Worktree</title>
      <link>https://blogs.dgplug.org/sandeepk/git-worktree</link>
      <description>&lt;![CDATA[A few days ago, during our office knowledge-sharing meeting, someone introduced the git worktree command. It lets you create a new branch parallel to your current working branch so you can start something new — or handle a hotfix — without stashing or committing your unfinished changes.&#xA;&#xA;It turned out to be incredibly useful. With git worktree, you can maintain multiple working directories linked to the same Git repository with almost no friction.&#xA;&#xA;---&#xA;&#xA;Why use worktrees?&#xA;&#xA;Imagine you&#39;re working on a long-running feature — say, an optimization — and suddenly you’re assigned an urgent production bug.&#xA;Typically, you would stash your changes or make a temporary commit, switch branches, fix the bug, then restore everything. It&#39;s annoying and error-prone.&#xA;&#xA;With worktrees, you can directly spin up a parallel working directory:&#xA;&#xA;git worktree add path&#xA;Example:&#xA;git worktree add ../hotfix&#xA;&#xA;This creates a new linked worktree, associated with your current repository, with its own metadata and branch checkout. Your original work remains untouched.&#xA;&#xA;---&#xA;&#xA;Removing a worktree&#xA;&#xA;Once you&#39;re done with the hotfix (or any task), removing the worktree is just as simple:&#xA;&#xA;git worktree remove path&#xA;&#xA;If you delete the directory manually, Git will eventually clean up its administrative files automatically (based on gc.worktreePruneExpire in git-config).&#xA;You can also remove stale entries explicitly:&#xA;&#xA;git worktree prune&#xA;&#xA;---&#xA;&#xA;Other useful worktree commands&#xA;&#xA;1. Create a throwaway worktree (detached HEAD)&#xA;&#xA;Perfect for quick experiments:&#xA;&#xA;git worktree add -d path&#xA;&#xA;2. Create a worktree for an existing branch&#xA;&#xA;git worktree add path branch&#xA;&#xA;This checks out the given branch into a new, isolated working directory.&#xA;&#xA;---&#xA;&#xA;Further reading&#xA;&#xA;To dive deeper into git worktree:&#xA;&#xA;Official docs: https://git-scm.com/docs/git-worktree&#xA;Or simply run:&#xA;&#xA;    git help worktree&#xA;  &#xA;&#xA;Cheers!&#xA;&#xA;#Git #TIL #Worktree]]&gt;</description>
      <content:encoded><![CDATA[<p>A few days ago, during our office knowledge-sharing meeting, someone introduced the <code>git worktree</code> command. It lets you create a new branch <em>parallel</em> to your current working branch so you can start something new — or handle a hotfix — <strong>without stashing or committing your unfinished changes</strong>.</p>

<p>It turned out to be incredibly useful. With <code>git worktree</code>, you can maintain multiple working directories linked to the same Git repository with almost no friction.</p>

<hr>

<h2 id="why-use-worktrees">Why use worktrees?</h2>

<p>Imagine you&#39;re working on a long-running feature — say, an optimization — and suddenly you’re assigned an urgent production bug.
Typically, you would stash your changes or make a temporary commit, switch branches, fix the bug, then restore everything. It&#39;s annoying and error-prone.</p>

<p>With worktrees, you can directly spin up a parallel working directory:</p>

<pre><code class="language-bash">git worktree add &lt;path&gt;
# Example:
git worktree add ../hotfix
</code></pre>

<p>This creates a <strong>new linked worktree</strong>, associated with your current repository, with its own metadata and branch checkout. Your original work remains untouched.</p>

<hr>

<h2 id="removing-a-worktree">Removing a worktree</h2>

<p>Once you&#39;re done with the hotfix (or any task), removing the worktree is just as simple:</p>

<pre><code class="language-bash">git worktree remove &lt;path&gt;
</code></pre>

<p>If you delete the directory manually, Git will eventually clean up its administrative files automatically (based on <code>gc.worktreePruneExpire</code> in <code>git-config</code>).
You can also remove stale entries explicitly:</p>

<pre><code class="language-bash">git worktree prune
</code></pre>

<hr>

<h2 id="other-useful-worktree-commands">Other useful worktree commands</h2>

<h3 id="1-create-a-throwaway-worktree-detached-head">1. Create a throwaway worktree (detached HEAD)</h3>

<p>Perfect for quick experiments:</p>

<pre><code class="language-bash">git worktree add -d &lt;path&gt;
</code></pre>

<h3 id="2-create-a-worktree-for-an-existing-branch">2. Create a worktree for an existing branch</h3>

<pre><code class="language-bash">git worktree add &lt;path&gt; &lt;branch&gt;
</code></pre>

<p>This checks out the given branch into a new, isolated working directory.</p>

<hr>

<h2 id="further-reading">Further reading</h2>

<p>To dive deeper into <code>git worktree</code>:</p>
<ul><li>Official docs: <a href="https://git-scm.com/docs/git-worktree" rel="nofollow">https://git-scm.com/docs/git-worktree</a></li>
<li>Or simply run:</li></ul>

<pre><code class="language-bash">  git help worktree
</code></pre>

<p>Cheers!</p>

<p><a href="/sandeepk/tag:Git" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">Git</span></a> <a href="/sandeepk/tag:TIL" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">TIL</span></a> <a href="/sandeepk/tag:Worktree" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">Worktree</span></a></p>
]]></content:encoded>
      <guid>https://blogs.dgplug.org/sandeepk/git-worktree</guid>
      <pubDate>Sun, 30 Nov 2025 13:27:11 +0000</pubDate>
    </item>
    <item>
      <title>Debugging maxlocksper_transaction: A Journey into Pytest Parallelism</title>
      <link>https://blogs.dgplug.org/sandeepk/debugging-max_locks_per_transaction-a-journey-into-pytest-parallelism</link>
      <description>&lt;![CDATA[So I was fixing some slow tests, and whenever I ran them through the pytest command, I was greeted with the dreaded maxlockspertransaction error.&#xA;&#xA;My first instinct? Just crank up the maxlockspertransaction from 64 to 1024.&#xA;&#xA;But... that didn’t feel right. I recreate my DB frequently, which means I’d have to set that value again and again. It felt like a hacky workaround rather than a proper solution.&#xA;&#xA;Then, like any developer, I started digging around — first checking the Confluence page for dev docs to see if anyone else had faced this issue. No luck. Then I moved to Slack, and that’s where I found this command someone had shared:&#xA;&#xA;pytest -n=0&#xA;&#xA;This was new to me. So, like any sane dev in 2025, I asked ChatGPT what this was about. That’s how I came across pytest-xdist.&#xA;&#xA;What is pytest-xdist?&#xA;&#xA;  The pytest-xdist plugin extends pytest with new test execution modes — the most common one is distributing tests across multiple CPUs to speed up test execution.&#xA;&#xA;What does pytest-xdist do?&#xA;&#xA;  Runs tests in parallel using numprocesses workers (Python processes), which is a game changer when:&#xA;  - You have a large test suite  &#xA;  - Each test takes a significant amount of time  &#xA;  - Your tests are independent (i.e., no shared global state)&#xA;&#xA;---&#xA;&#xA;That’s pretty much it — I plugged in pytest -n=0 and boom, no more transaction locks errors.  &#xA;&#xA;Cheers!&#xA;&#xA;References&#xA;https://pytest-xdist.readthedocs.io/en/stable/&#xA;https://docs.pytest.org/en/stable/reference/reference.html&#xA;&#xA;#pytest #Python #chatgpt #debugging&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>So I was fixing some slow tests, and whenever I ran them through the <code>pytest</code> command, I was greeted with the dreaded <code>max_locks_per_transaction</code> error.</p>

<p>My first instinct? Just crank up the <code>max_locks_per_transaction</code> from 64 to 1024.</p>

<p>But... that didn’t feel right. I recreate my DB frequently, which means I’d have to set that value again and again. It felt like a hacky workaround rather than a proper solution.</p>

<p>Then, like any developer, I started digging around — first checking the Confluence page for dev docs to see if anyone else had faced this issue. No luck. Then I moved to Slack, and that’s where I found this command someone had shared:</p>

<pre><code class="language-bash">pytest -n=0
</code></pre>

<p>This was new to me. So, like any sane dev in 2025, I asked ChatGPT what this was about. That’s how I came across <code>pytest-xdist</code>.</p>

<h2 id="what-is-pytest-xdist">What is <code>pytest-xdist</code>?</h2>

<blockquote><p>The <code>pytest-xdist</code> plugin extends pytest with new test execution modes — the most common one is distributing tests across multiple CPUs to <strong>speed up test execution</strong>.</p></blockquote>

<h2 id="what-does-pytest-xdist-do">What does <code>pytest-xdist</code> do?</h2>

<blockquote><p>Runs tests in <strong>parallel</strong> using <code>&lt;numprocesses&gt;</code> workers (Python processes), which is a game changer when:
– You have a large test suite<br>
– Each test takes a significant amount of time<br>
– Your tests are independent (i.e., no shared global state)</p></blockquote>

<hr>

<p>That’s pretty much it — I plugged in <code>pytest -n=0</code> and boom, no more transaction locks errors.</p>

<p>Cheers!</p>

<p>References
– <a href="https://pytest-xdist.readthedocs.io/en/stable/" rel="nofollow">https://pytest-xdist.readthedocs.io/en/stable/</a>
– <a href="https://docs.pytest.org/en/stable/reference/reference.html" rel="nofollow">https://docs.pytest.org/en/stable/reference/reference.html</a></p>

<p><a href="/sandeepk/tag:pytest" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">pytest</span></a> <a href="/sandeepk/tag:Python" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">Python</span></a> <a href="/sandeepk/tag:chatgpt" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">chatgpt</span></a> <a href="/sandeepk/tag:debugging" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">debugging</span></a></p>
]]></content:encoded>
      <guid>https://blogs.dgplug.org/sandeepk/debugging-max_locks_per_transaction-a-journey-into-pytest-parallelism</guid>
      <pubDate>Wed, 16 Jul 2025 17:07:59 +0000</pubDate>
    </item>
    <item>
      <title>ChatGPT and Images</title>
      <link>https://blogs.dgplug.org/sandeepk/chatgpt-and-images</link>
      <description>&lt;![CDATA[I’ve been working on a few side projects and using ChatGPT for ideation and brainstorming around ideas and features for the MVP. As part of this, I needed a logo for my app. Naturally, I turned to AI to help me generate one.&#xA;&#xA;However, I noticed that when generating images, ChatGPT doesn’t always follow the guidelines perfectly. Each time I asked for a new version, it would create a completely different image, which made it difficult to iterate or make small tweaks.&#xA;&#xA;But I found a better way.&#xA;&#xA;Instead of generating a brand new image every time, I first explained my app idea and the name. ChatGPT generated an image I liked.&#xA;&#xA;So I asked ChatGPT to generate the JSON for the image instead. I then manually tweaked the JSON file to adjust things exactly the way I wanted. When I asked ChatGPT to generate the image based on the updated JSON, it finally created the image as per my request — no random changes, just the specific adjustments I needed.&#xA;&#xA;Exploration Phase&#xA;&#xA;SplitX logo&#xA;&#xA;{&#xA;  &#34;image&#34;: {&#xA;    &#34;filename&#34;: &#34;splitXiconwithtext.png&#34;,&#xA;    &#34;backgroundcolor&#34;: &#34;black&#34;,&#xA;    &#34;elements&#34;: [&#xA;      {&#xA;        &#34;type&#34;: &#34;text&#34;,&#xA;        &#34;content&#34;: &#34;SplitX&#34;,&#xA;        &#34;fontstyle&#34;: &#34;bold&#34;,&#xA;        &#34;fontcolor&#34;: &#34;white&#34;,&#xA;        &#34;position&#34;: &#34;center&#34;,&#xA;        &#34;fontsize&#34;: &#34;large&#34;&#xA;      },&#xA;      {&#xA;        &#34;type&#34;: &#34;shape&#34;,&#xA;        &#34;shapetype&#34;: &#34;X&#34;,&#xA;        &#34;style&#34;: &#34;geometric split&#34;,&#xA;        &#34;colors&#34;: [&#xA;          {&#xA;            &#34;section&#34;: &#34;top-left&#34;,&#xA;            &#34;gradient&#34;: [&#34;#FF4E50&#34;, &#34;#F9D423&#34;]&#xA;          },&#xA;          {&#xA;            &#34;section&#34;: &#34;bottom-left&#34;,&#xA;            &#34;gradient&#34;: [&#34;#F9D423&#34;, &#34;#FC913A&#34;]&#xA;          },&#xA;          {&#xA;            &#34;section&#34;: &#34;top-right&#34;,&#xA;            &#34;gradient&#34;: [&#34;#24C6DC&#34;, &#34;#514A9D&#34;]&#xA;          },&#xA;          {&#xA;            &#34;section&#34;: &#34;bottom-right&#34;,&#xA;            &#34;gradient&#34;: [&#34;#514A9D&#34;, &#34;#E55D87&#34;]&#xA;          }&#xA;        ],&#xA;        &#34;position&#34;: &#34;center behind text&#34;,&#xA;        &#34;stylenotes&#34;: &#34;Each quadrant of the X has a distinct gradient, giving a modern and vibrant look. The X is split visually in the middle, aligning with the &#39;Split&#39; theme.&#34;&#xA;      }&#xA;    ]&#xA;  }&#xA;}&#xA;Final Design&#xA;&#xA;SplitX logo&#xA;Updated JSON&#xA;{&#xA;  &#34;image&#34;: {&#xA;    &#34;filename&#34;: &#34;splitXiconwithtext.png&#34;,&#xA;    &#34;backgroundcolor&#34;: &#34;transparent&#34;,&#xA;    &#34;elements&#34;: [&#xA;      {&#xA;        &#34;type&#34;: &#34;shape&#34;,&#xA;        &#34;shapetype&#34;: &#34;X&#34;,&#xA;        &#34;style&#34;: &#34;geometric split&#34;,&#xA;        &#34;colors&#34;: [&#xA;          {&#xA;            &#34;section&#34;: &#34;top-left&#34;,&#xA;            &#34;gradient&#34;: [&#xA;              &#34;#FF4E50&#34;,&#xA;              &#34;#F9D423&#34;&#xA;            ]&#xA;          },&#xA;          {&#xA;            &#34;section&#34;: &#34;bottom-left&#34;,&#xA;            &#34;gradient&#34;: [&#xA;              &#34;#F9D423&#34;,&#xA;              &#34;#FC913A&#34;&#xA;            ]&#xA;          },&#xA;          {&#xA;            &#34;section&#34;: &#34;top-right&#34;,&#xA;            &#34;gradient&#34;: [&#xA;              &#34;#24C6DC&#34;,&#xA;              &#34;#514A9D&#34;&#xA;            ]&#xA;          },&#xA;          {&#xA;            &#34;section&#34;: &#34;bottom-right&#34;,&#xA;            &#34;gradient&#34;: [&#xA;              &#34;#514A9D&#34;,&#xA;              &#34;#E55D87&#34;&#xA;            ]&#xA;          }&#xA;        ],&#xA;        &#34;position&#34;: &#34;center &#34;,&#xA;        &#34;stylenotes&#34;: &#34;Each quadrant of the X has a distinct gradient, giving a modern and vibrant look. The X is split visually in the middle, aligning with the &#39;Split&#39; theme.&#34;&#xA;      }&#xA;    ]&#xA;  }&#xA;}&#xA;&#xA;If you want to tweak or refine an image, first generate the JSON, make your changes there, and then ask ChatGPT to generate the image using your updated JSON. This gives you much more control over the final result.&#xA;&#xA;Cheers!&#xA;&#xA;P.S. Feel free to check out the app — it&#39;s live now at https://splitx.org/. Would love to hear what you think!]]&gt;</description>
      <content:encoded><![CDATA[<p>I’ve been working on a few side projects and using ChatGPT for ideation and brainstorming around ideas and features for the MVP. As part of this, I needed a logo for my app. Naturally, I turned to AI to help me generate one.</p>

<p>However, I noticed that when generating images, ChatGPT doesn’t always follow the guidelines perfectly. Each time I asked for a new version, it would create a completely different image, which made it difficult to iterate or make small tweaks.</p>

<p>But I found a better way.</p>

<p>Instead of generating a brand new image every time, I first explained my app idea and the name. ChatGPT generated an image I liked.</p>

<p>So I asked ChatGPT to generate the JSON for the image instead. I then manually tweaked the JSON file to adjust things exactly the way I wanted. When I asked ChatGPT to generate the image based on the updated JSON, it finally created the image as per my request — no random changes, just the specific adjustments I needed.</p>

<h3 id="exploration-phase">Exploration Phase</h3>

<p><img src="https://raw.githubusercontent.com/Skchoudhary/blog-asset/master/dgplug-blog/slpitX_icon_with_text.png" alt="SplitX logo"></p>

<pre><code class="language-json">{
  &#34;image&#34;: {
    &#34;file_name&#34;: &#34;splitX_icon_with_text.png&#34;,
    &#34;background_color&#34;: &#34;black&#34;,
    &#34;elements&#34;: [
      {
        &#34;type&#34;: &#34;text&#34;,
        &#34;content&#34;: &#34;SplitX&#34;,
        &#34;font_style&#34;: &#34;bold&#34;,
        &#34;font_color&#34;: &#34;white&#34;,
        &#34;position&#34;: &#34;center&#34;,
        &#34;font_size&#34;: &#34;large&#34;
      },
      {
        &#34;type&#34;: &#34;shape&#34;,
        &#34;shape_type&#34;: &#34;X&#34;,
        &#34;style&#34;: &#34;geometric split&#34;,
        &#34;colors&#34;: [
          {
            &#34;section&#34;: &#34;top-left&#34;,
            &#34;gradient&#34;: [&#34;#FF4E50&#34;, &#34;#F9D423&#34;]
          },
          {
            &#34;section&#34;: &#34;bottom-left&#34;,
            &#34;gradient&#34;: [&#34;#F9D423&#34;, &#34;#FC913A&#34;]
          },
          {
            &#34;section&#34;: &#34;top-right&#34;,
            &#34;gradient&#34;: [&#34;#24C6DC&#34;, &#34;#514A9D&#34;]
          },
          {
            &#34;section&#34;: &#34;bottom-right&#34;,
            &#34;gradient&#34;: [&#34;#514A9D&#34;, &#34;#E55D87&#34;]
          }
        ],
        &#34;position&#34;: &#34;center behind text&#34;,
        &#34;style_notes&#34;: &#34;Each quadrant of the X has a distinct gradient, giving a modern and vibrant look. The X is split visually in the middle, aligning with the &#39;Split&#39; theme.&#34;
      }
    ]
  }
}
</code></pre>

<h3 id="final-design">Final Design</h3>

<p><img src="https://raw.githubusercontent.com/Skchoudhary/blog-asset/master/dgplug-blog/ChatGPT%20Image%20Jul%201,%202025,%2011_07_23%20PM.png" alt="SplitX logo">
Updated JSON</p>

<pre><code class="language-json">{
  &#34;image&#34;: {
    &#34;file_name&#34;: &#34;splitX_icon_with_text.png&#34;,
    &#34;background_color&#34;: &#34;transparent&#34;,
    &#34;elements&#34;: [
      {
        &#34;type&#34;: &#34;shape&#34;,
        &#34;shape_type&#34;: &#34;X&#34;,
        &#34;style&#34;: &#34;geometric split&#34;,
        &#34;colors&#34;: [
          {
            &#34;section&#34;: &#34;top-left&#34;,
            &#34;gradient&#34;: [
              &#34;#FF4E50&#34;,
              &#34;#F9D423&#34;
            ]
          },
          {
            &#34;section&#34;: &#34;bottom-left&#34;,
            &#34;gradient&#34;: [
              &#34;#F9D423&#34;,
              &#34;#FC913A&#34;
            ]
          },
          {
            &#34;section&#34;: &#34;top-right&#34;,
            &#34;gradient&#34;: [
              &#34;#24C6DC&#34;,
              &#34;#514A9D&#34;
            ]
          },
          {
            &#34;section&#34;: &#34;bottom-right&#34;,
            &#34;gradient&#34;: [
              &#34;#514A9D&#34;,
              &#34;#E55D87&#34;
            ]
          }
        ],
        &#34;position&#34;: &#34;center &#34;,
        &#34;style_notes&#34;: &#34;Each quadrant of the X has a distinct gradient, giving a modern and vibrant look. The X is split visually in the middle, aligning with the &#39;Split&#39; theme.&#34;
      }
    ]
  }
}
</code></pre>

<p>If you want to tweak or refine an image, first generate the JSON, make your changes there, and then ask ChatGPT to generate the image using your updated JSON. This gives you much more control over the final result.</p>

<p>Cheers!</p>

<p>P.S. Feel free to check out the app — it&#39;s live now at <a href="https://splitx.org/" rel="nofollow">https://splitx.org/</a>. Would love to hear what you think!</p>
]]></content:encoded>
      <guid>https://blogs.dgplug.org/sandeepk/chatgpt-and-images</guid>
      <pubDate>Thu, 03 Jul 2025 13:28:47 +0000</pubDate>
    </item>
    <item>
      <title>Blog Questions Challenge 2025</title>
      <link>https://blogs.dgplug.org/sandeepk/blog-questions-challenge-2025</link>
      <description>&lt;![CDATA[1. Why did you make the blog in the first place?&#xA;This blog initially started as part of the summer training by DGPLUG, where the good folks emphasize the importance of blogging and encourage everyone to write—about anything! That motivation got me into the habit, and I’ve been blogging on and off ever since.&#xA;2. What platform are you using to manage your blog and why did you choose it?&#xA;I primarily write on WriteFreely, hosted by Kushal, who was kind enough to host an instance. I also occasionally write on my WordPress blog. So yeah, I have two blogs.&#xA;3. Have you blogged on other platforms before?&#xA;I started with WordPress because it was a simple and fast way to get started. Even now, I sometimes post there, but most of my recent posts have moved to the WriteFreely instance.&#xA;4. How do you write your posts?&#xA;I usually just sit down and write everything in one go. Followed by editing part—skimming through it once, making quick changes, and then hitting publish. &#xA;5. When do you feel most inspired to write?&#xA;Honestly, I don’t wait for inspiration. I write whenever I feel like it—sometimes in a diary, sometimes on my laptop. A few of those thoughts end up as blog posts, while the rest get lost in random notes and files.&#xA;6. Do you publish immediately after writing or do you let it simmer a bit as a draft?&#xA;It depends. After reading a few books and articles on writing, I started following a simple process: finish a draft in one sitting, come back to it later for editing, and then publish.&#xA;7. Your favorite post on your blog?&#xA;Ahh! This blog post on Google Cloud IAM is one I really like because people told me it was well-written! :)&#xA;8. Any future plans for your blog? Maybe a redesign, changing the tag system, etc.?&#xA;Nope! I like it as it is. Keeping it simple for now.&#xA;&#xA;A big thanks to Jason for mentioning me in the challenge! &#xA;&#xA;Cheers!]]&gt;</description>
      <content:encoded><![CDATA[<h2 id="1-why-did-you-make-the-blog-in-the-first-place">1. Why did you make the blog in the first place?</h2>

<p>This blog initially started as part of the summer training by DGPLUG, where the good folks emphasize the importance of blogging and encourage everyone to write—about anything! That motivation got me into the habit, and I’ve been blogging on and off ever since.</p>

<h2 id="2-what-platform-are-you-using-to-manage-your-blog-and-why-did-you-choose-it">2. What platform are you using to manage your blog and why did you choose it?</h2>

<p>I primarily write on WriteFreely, hosted by <a href="https://kushaldas.in/" rel="nofollow">Kushal</a>, who was kind enough to host an instance. I also occasionally write on my WordPress blog. So yeah, I have two blogs.</p>

<h2 id="3-have-you-blogged-on-other-platforms-before">3. Have you blogged on other platforms before?</h2>

<p>I started with WordPress because it was a simple and fast way to get started. Even now, I sometimes post there, but most of my recent posts have moved to the <a href="https://blogs.dgplug.org/" rel="nofollow">WriteFreely instance</a>.</p>

<h2 id="4-how-do-you-write-your-posts">4. How do you write your posts?</h2>

<p>I usually just sit down and write everything in one go. Followed by editing part—skimming through it once, making quick changes, and then hitting publish.</p>

<h2 id="5-when-do-you-feel-most-inspired-to-write">5. When do you feel most inspired to write?</h2>

<p>Honestly, I don’t wait for inspiration. I write whenever I feel like it—sometimes in a diary, sometimes on my laptop. A few of those thoughts end up as blog posts, while the rest get lost in random notes and files.</p>

<h2 id="6-do-you-publish-immediately-after-writing-or-do-you-let-it-simmer-a-bit-as-a-draft">6. Do you publish immediately after writing or do you let it simmer a bit as a draft?</h2>

<p>It depends. After reading a few books and articles on writing, I started following a simple process: finish a draft in one sitting, come back to it later for editing, and then publish.</p>

<h2 id="7-your-favorite-post-on-your-blog">7. Your favorite post on your blog?</h2>

<p>Ahh! This <a href="https://sandeepchoudharyme.wordpress.com/2019/07/08/google-cloud-iam-identity-and-access-management/" rel="nofollow">blog post</a> on Google Cloud IAM is one I really like because people told me it was well-written! :)</p>

<h2 id="8-any-future-plans-for-your-blog-maybe-a-redesign-changing-the-tag-system-etc">8. Any future plans for your blog? Maybe a redesign, changing the tag system, etc.?</h2>

<p>Nope! I like it as it is. Keeping it simple for now.</p>

<p>A big thanks to <a href="https://janusworx.com" rel="nofollow">Jason</a> for mentioning me in the <a href="https://janusworx.com/work/blog-questions-challenge-2025/" rel="nofollow">challenge</a>!</p>

<p>Cheers!</p>
]]></content:encoded>
      <guid>https://blogs.dgplug.org/sandeepk/blog-questions-challenge-2025</guid>
      <pubDate>Sat, 29 Mar 2025 05:32:42 +0000</pubDate>
    </item>
    <item>
      <title>CSS: Combinators </title>
      <link>https://blogs.dgplug.org/sandeepk/css-combinators</link>
      <description>&lt;![CDATA[In CSS, combinators are used to select content by combining selectors in specific relationships. There are different types of relationships that can be used to combine selectors.&#xA; &#xA;Descendant combinator&#xA;The descendant combinator is represented by a space &#34; &#34;  and typically used between two selectors. It selects the second selector if the first selector is the ancestor (parent, parent parent&#39;s) element. These selectors are called the descendant selectors.&#xA;&#xA;.cover p {&#xA;    color: red;&#xA;}&#xA;div class=&#34;cover&#34;pText in .cover/p/div&#xA;pText not in .cover/p&#xA;In this example, the text &#34;Text in .cover&#34; will be displayed in red.&#xA;&#xA;Child combinators&#xA;The child combinator is represented by &#34;  &#34; and is used between two selectors. In this, an element is only selected if the second selector is the direct child of the first selector element. This means there should not be any other selector between the first selector element and second element selector.&#xA;&#xA;ul   li {&#xA;    border-top: 5px solid red;&#xA;} &#xA;ul&#xA;    liUnordered item/li&#xA;    liUnordered item&#xA;        ol&#xA;            liItem 1/li&#xA;            liItem 2/li&#xA;        /ol&#xA;    /li&#xA;/ul&#xA;In this example, the li element with the text &#34;Unordered item&#34; will have a red top border.&#xA;&#xA;Adjacent sibling combinator&#xA;The adjacent sibling combinator is represented by &#34;+&#34;  is placed between the two CSS selector. In this element is selected if the selector element is directly followed by the first element selector or only the adjacent sibling&#xA;h1 + span {&#xA;    font-weight: bold;&#xA;    background-color: #333;&#xA;    color: #fff;&#xA;    padding: .5em;&#xA;}&#xA;div&#xA;    h1A heading/h1&#xA;    spanVeggies es bonus vobis, proinde vos postulo essum magis kohlrabi welsh onion daikon amaranth tatsoi tomatillo&#xA;            melon azuki bean garlic./span&#xA;&#xA;    spanGumbo beet greens corn soko endive gumbo gourd. Parsley shallot courgette tatsoi pea sprouts fava bean collard&#xA;            greens dandelion okra wakame tomato. Dandelion cucumber earthnut pea peanut soko zucchini./span&#xA;/div&#xA;In this example, the first span element will have the given CSS properties.&#xA;&#xA;General sibling combinator&#xA;The general sibling combinator is represented by &#34;~&#34;.  It selects all the sibling element, not only the direct sibling element, then we use the general sibling combinator.&#xA;h1 ~ h2 {&#xA;    font-weight: bold;&#xA;    background-color: #333;&#xA;    color: #fff;&#xA;    padding: .5em;&#xA;}&#xA;article&#xA;    h1A heading/h1&#xA;    h2I am a paragraph./h2&#xA;    divI am a div/div&#xA;    h2I am another paragraph./h2&#xA;/article&#xA;In this example, every h2 element will have the given CSS properties.&#xA;&#xA;CSS combinators provide powerful ways to select and style content based on their relationships in the HTML structure. By understanding combinators, we can create clean, maintainable, and responsive web designs.&#xA;&#xA;Cheers!&#xA;&#xA;References&#xA;MDN Web Docs&#xA;&#xA;CSS&#xA;Combinators&#xA;WebDevelopment&#xA;FrontendDev &#xA;&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>In CSS, combinators are used to select content by combining selectors in specific relationships. There are different types of relationships that can be used to combine selectors.</p>

<h2 id="descendant-combinator">Descendant combinator</h2>

<p>The descendant combinator is represented by a space “ ”  and typically used between two selectors. It selects the second selector if the first selector is the ancestor (parent, parent parent&#39;s) element. These selectors are called the descendant selectors.</p>

<pre><code class="language-css">.cover p {
    color: red;
}
</code></pre>

<pre><code class="language-html">&lt;div class=&#34;cover&#34;&gt;&lt;p&gt;Text in .cover&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Text not in .cover&lt;/p&gt;
</code></pre>

<p><em>In this example, the text “Text in .cover” will be displayed in red.</em></p>

<h2 id="child-combinators">Child combinators</h2>

<p>The child combinator is represented by “&gt;” and is used between two selectors. In this, an element is only selected if the second selector is the direct child of the first selector element. This means there should not be any other selector between the first selector element and second element selector.</p>

<pre><code class="language-css">ul &gt; li {
    border-top: 5px solid red;
} 
</code></pre>

<pre><code class="language-html">&lt;ul&gt;
    &lt;li&gt;Unordered item&lt;/li&gt;
    &lt;li&gt;Unordered item
        &lt;ol&gt;
            &lt;li&gt;Item 1&lt;/li&gt;
            &lt;li&gt;Item 2&lt;/li&gt;
        &lt;/ol&gt;
    &lt;/li&gt;
&lt;/ul&gt;
</code></pre>

<p><em>In this example, the <code>&lt;li&gt;</code> element with the text “Unordered item” will have a red top border.</em></p>

<h2 id="adjacent-sibling-combinator">Adjacent sibling combinator</h2>

<p>The adjacent sibling combinator is represented by “+”  is placed between the two CSS selector. In this element is selected if the selector element is directly followed by the first element selector or only the adjacent sibling</p>

<pre><code class="language-css">h1 + span {
    font-weight: bold;
    background-color: #333;
    color: #fff;
    padding: .5em;
}
</code></pre>

<pre><code class="language-html">&lt;div&gt;
    &lt;h1&gt;A heading&lt;/h1&gt;
    &lt;span&gt;Veggies es bonus vobis, proinde vos postulo essum magis kohlrabi welsh onion daikon amaranth tatsoi tomatillo
            melon azuki bean garlic.&lt;/span&gt;

    &lt;span&gt;Gumbo beet greens corn soko endive gumbo gourd. Parsley shallot courgette tatsoi pea sprouts fava bean collard
            greens dandelion okra wakame tomato. Dandelion cucumber earthnut pea peanut soko zucchini.&lt;/span&gt;
&lt;/div&gt;
</code></pre>

<p><em>In this example, the first <span> element will have the given CSS properties.</em></p>

<h2 id="general-sibling-combinator">General sibling combinator</h2>

<p>The general sibling combinator is represented by “~“.  It selects all the sibling element, not only the direct sibling element, then we use the general sibling combinator.</p>

<pre><code class="language-css">h1 ~ h2 {
    font-weight: bold;
    background-color: #333;
    color: #fff;
    padding: .5em;
}
</code></pre>

<pre><code class="language-html">&lt;article&gt;
    &lt;h1&gt;A heading&lt;/h1&gt;
    &lt;h2&gt;I am a paragraph.&lt;/h2&gt;
    &lt;div&gt;I am a div&lt;/div&gt;
    &lt;h2&gt;I am another paragraph.&lt;/h2&gt;
&lt;/article&gt;
</code></pre>

<p><em>In this example, every <code>&lt;h2&gt;</code> element will have the given CSS properties.</em></p>

<p>CSS combinators provide powerful ways to select and style content based on their relationships in the HTML structure. By understanding combinators, we can create clean, maintainable, and responsive web designs.</p>

<p>Cheers!</p>

<p><strong>References</strong>
– <a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators" rel="nofollow">MDN Web Docs</a></p>

<p><a href="/sandeepk/tag:CSS" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">CSS</span></a>
<a href="/sandeepk/tag:Combinators" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">Combinators</span></a>
<a href="/sandeepk/tag:WebDevelopment" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">WebDevelopment</span></a>
<a href="/sandeepk/tag:FrontendDev" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">FrontendDev</span></a></p>
]]></content:encoded>
      <guid>https://blogs.dgplug.org/sandeepk/css-combinators</guid>
      <pubDate>Sun, 28 May 2023 14:42:23 +0000</pubDate>
    </item>
    <item>
      <title>Converting HTML Tables to CSV</title>
      <link>https://blogs.dgplug.org/sandeepk/converting-html-tables-to-csv</link>
      <description>&lt;![CDATA[Today, I decided to analyze my bank account statement by downloading it from the day I opened my bank account. To my surprise, it was presented as a web page. Initially, my inner developer urged me to write code to scrape that data. However, feeling a bit lazy, I postponed doing so.&#xA;&#xA;Later in the evening, I searched the web to find an alternate way to extract the data and discovered that HTML tables can be converted to CSV files. All I had to do was save the code in CSV format. I opened the Chrome browser&#39;s inspect code feature, copied the table, saved it with the CSV extension, and then opened the file with LibreOffice. Voila! I had the spreadsheet with all my transactions.&#xA;&#xA;Cheers!&#xA;&#xA;TIL&#xA;CSV&#xA;HTML Table&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>Today, I decided to analyze my bank account statement by downloading it from the day I opened my bank account. To my surprise, it was presented as a web page. Initially, my inner developer urged me to write code to scrape that data. However, feeling a bit lazy, I postponed doing so.</p>

<p>Later in the evening, I searched the web to find an alternate way to extract the data and discovered that HTML tables can be converted to CSV files. All I had to do was save the code in CSV format. I opened the Chrome browser&#39;s inspect code feature, copied the table, saved it with the CSV extension, and then opened the file with LibreOffice. Voila! I had the spreadsheet with all my transactions.</p>

<p>Cheers!</p>

<p><a href="/sandeepk/tag:TIL" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">TIL</span></a>
<a href="/sandeepk/tag:CSV" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">CSV</span></a>
<a href="/sandeepk/tag:HTML" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">HTML</span></a> Table</p>
]]></content:encoded>
      <guid>https://blogs.dgplug.org/sandeepk/converting-html-tables-to-csv</guid>
      <pubDate>Sat, 15 Apr 2023 17:41:58 +0000</pubDate>
    </item>
    <item>
      <title>The Debug Diary - Chapter I</title>
      <link>https://blogs.dgplug.org/sandeepk/the-debug-diary-chapter-i</link>
      <description>&lt;![CDATA[The Debug Diary - Chapter I&#xA;&#xA;Lately, I was debugging an issue with the importer tasks of our codebase and came across a code block which looks fine but makes an extra database query in the loop. When you have a look at the Django ORM query&#xA;&#xA;jatovehicles = JatoVehicle.objects.filter(&#xA;    yearin=availableyears,morefilters&#xA;).only(&#34;manufacturercode&#34;, &#34;uid&#34;, &#34;year&#34;, &#34;model&#34;, &#34;trim&#34;)&#xA;&#xA;for entry in jatovehicles.iterator():&#xA;    if entry.manufacturercode:&#xA;        logic&#xA;    ymtkey = (entry.year, entry.model, entry.trimprocessed)&#xA;...&#xA;you will notice we are using only, which only loads the set of fields mentioned and deferred other fields, but in the loop, we are using the field trimprocessed which is a deferred field and will result in an extra database call.&#xA;&#xA;Now, as we have identified the performance issue, the best way to handle the cases like this is to use values or valueslist. The use of only should be discouraged in the cases like these.&#xA;&#xA;Update code will look like this&#xA;jatovehicles = JatoVehicle.objects.filter(&#xA;    yearin=availableyears,more-filters).valueslist(&#xA;    &#34;manufacturercode&#34;,&#xA;    &#34;uid&#34;,&#xA;    &#34;year&#34;,&#xA;    &#34;model&#34;,&#xA;    &#34;trimprocessed&#34;,&#xA;    named=True,&#xA;)&#xA;&#xA;for entry in jatovehicles.iterator():&#xA;    if entry.manufacturercode:&#xA;        logic&#xA;    ymtkey = (entry.year, entry.model, entry.trimprocessed)&#xA;...&#xA;&#xA;By doing this, we are safe from accessing the fields which are not mentioned in the valueslist. If anyone tries to do so, an exception will be raised.&#xA;&#xA;** By using named=True we get the result as a named tuple which makes it easy to access the values :)&#xA;&#xA; &#xA;Cheers!&#xA;&#xA;Django&#xA;ORM&#xA;Debug]]&gt;</description>
      <content:encoded><![CDATA[<h2 id="the-debug-diary-chapter-i">The Debug Diary – Chapter I</h2>

<p>Lately, I was debugging an issue with the importer tasks of our codebase and came across a code block which looks fine but makes an extra database query in the loop. When you have a look at the Django ORM query</p>

<pre><code class="language-python">jato_vehicles = JatoVehicle.objects.filter(
    year__in=available_years,&lt;more_filters&gt;
).only(&#34;manufacturer_code&#34;, &#34;uid&#34;, &#34;year&#34;, &#34;model&#34;, &#34;trim&#34;)

for entry in jato_vehicles.iterator():
    if entry.manufacturer_code:
        &lt;logic&gt;
    ymt_key = (entry.year, entry.model, entry.trim_processed)
...
</code></pre>

<p>you will notice we are using <code>only</code>, which only loads the set of fields mentioned and deferred other fields, but in the loop, we are using the field <code>trim_processed</code> which is a deferred field and will result in an extra database call.</p>

<p>Now, as we have identified the performance issue, the best way to handle the cases like this is to use <code>values</code> or <code>values_list</code>. The use of <code>only</code> should be discouraged in the cases like these.</p>

<p>Update code will look like this</p>

<pre><code class="language-python">jato_vehicles = JatoVehicle.objects.filter(
    year__in=available_years,&lt;more-filters&gt;).values_list(
    &#34;manufacturer_code&#34;,
    &#34;uid&#34;,
    &#34;year&#34;,
    &#34;model&#34;,
    &#34;trim_processed&#34;,
    named=True,
)

for entry in jato_vehicles.iterator():
    if entry.manufacturer_code:
        &lt;logic&gt;
    ymt_key = (entry.year, entry.model, entry.trim_processed)
...
</code></pre>

<p>By doing this, we are safe from accessing the fields which are not mentioned in the <code>values_list</code>. If anyone tries to do so, an exception will be raised.</p>

<p>** By using <code>named=True</code> we get the result as a named tuple which makes it easy to access the values :)</p>

<p>Cheers!</p>

<p><a href="/sandeepk/tag:Django" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">Django</span></a>
<a href="/sandeepk/tag:ORM" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">ORM</span></a>
<a href="/sandeepk/tag:Debug" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">Debug</span></a></p>
]]></content:encoded>
      <guid>https://blogs.dgplug.org/sandeepk/the-debug-diary-chapter-i</guid>
      <pubDate>Tue, 30 Aug 2022 07:34:12 +0000</pubDate>
    </item>
    <item>
      <title>Django: How to acquire a lock on the database rows? </title>
      <link>https://blogs.dgplug.org/sandeepk/django-how-to-acquire-a-lock-on-the-database-rows</link>
      <description>&lt;![CDATA[selectforupdate is the answer if you want to acquire a lock on the row. The lock is only released after the transaction is completed. This is similar to the Select for update statement in the SQL query.&#xA;&#xA;      Dealership.objects.selectforupdate().get(pk=&#39;iamid&#39;)&#xA;      # Here lock is only required on Dealership object&#xA;      Dealership.objects.selectrelated(&#39;oem&#39;).selectforupdate(of=(&#39;self&#39;,))&#xA;selectforupdate have these four arguments with these default value&#xA;nowait=False&#xA;skiplocked=False&#xA;of=()&#xA;nokey=False&#xA;&#xA;Let&#39;s see what these all arguments mean&#xA;&#xA;nowait&#xA;Think of the scenario where the lock is already acquired by another query, in this case, you want your query to wait or raise an error, This behavior can be controlled by nowait, If nowait=True we will raise the DatabaseError otherwise it will wait for the lock to be released.&#xA;skiplocked&#xA;As somewhat name implies, it helps to decide whether to consider a locked row in the evaluated query. If the skiplocked=true locked rows will not be considered.&#xA;&#xA;  nowait and skiplocked are mutually exclusive using both together will raise ValueError&#xA;&#xA;of&#xA;In selectforupdate when the query is evaluated, the lock is also acquired on the select related rows as in the query. If one doesn&#39;t wish the same, they can use of where they can specify fields to acquire a lock on&#xA;      Dealership.objects.selectrelated(&#39;oem&#39;).selectforupdate(of=(&#39;self&#39;,))&#xA;Just be sure we don&#39;t have any nullable relation with OEM&#xA;nokey&#xA;This helps you to create a weak lock. This means the other query can create new rows which refer to the locked rows (any reference relationship).&#xA;&#xA;Few more important points to keep in mind selectforupdate doesn&#39;t allow nullable relations, you have to explicitly exclude these nullable conditions. In auto-commit mode, selectforupdate fails with error TransactionManagementError you have to add code in a transaction explicitly. I have struggled around these points :).&#xA;&#xA;Here is all about selectforupdate which you require to know to use in your code and to do changes to your database.&#xA;&#xA;Cheers!&#xA;&#xA;Python&#xA;Django&#xA;ORM&#xA;Database&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p><code>select_for_update</code> is the answer if you want to acquire a lock on the row. The lock is only released after the transaction is completed. This is similar to the <code>Select for update statement</code> in the SQL query.</p>

<pre><code class="language-python">&gt;&gt;&gt; Dealership.objects.select_for_update().get(pk=&#39;iamid&#39;)
&gt;&gt;&gt; # Here lock is only required on Dealership object
&gt;&gt;&gt; Dealership.objects.select_related(&#39;oem&#39;).select_for_update(of=(&#39;self&#39;,))
</code></pre>

<p><code>select_for_update</code> have these four arguments with these default value
– nowait=False
– skip<em>locked=False
– of=()
– no</em>key=False</p>

<p>Let&#39;s see what these all arguments mean</p>

<h2 id="nowait">nowait</h2>

<p>Think of the scenario where the lock is already acquired by another query, in this case, you want your query to wait or raise an error, This behavior can be controlled by <code>nowait</code>, If <code>nowait=True</code> we will raise the <code>DatabaseError</code> otherwise it will wait for the lock to be released.</p>

<h2 id="skip-locked">skip_locked</h2>

<p>As somewhat name implies, it helps to decide whether to consider a locked row in the evaluated query. If the <code>skip_locked=true</code> locked rows will not be considered.</p>

<blockquote><p>nowait and skip_locked are mutually exclusive using both together will raise ValueError</p></blockquote>

<h2 id="of">of</h2>

<p>In <code>select_for_update</code> when the query is evaluated, the lock is also acquired on the select related rows as in the query. If one doesn&#39;t wish the same, they can use <code>of</code> where they can specify fields to acquire a lock on</p>

<pre><code class="language-python">&gt;&gt;&gt; Dealership.objects.select_related(&#39;oem&#39;).select_for_update(of=(&#39;self&#39;,))
# Just be sure we don&#39;t have any nullable relation with OEM
</code></pre>

<h2 id="no-key">no_key</h2>

<p>This helps you to create a weak lock. This means the other query can create new rows which refer to the locked rows (any reference relationship).</p>

<p>Few more important points to keep in mind <code>select_for_update</code> doesn&#39;t allow nullable relations, you have to explicitly exclude these nullable conditions. In auto-commit mode, <code>select_for_update</code> fails with error <code>TransactionManagementError</code> you have to add code in a transaction explicitly. I have struggled around these points :).</p>

<p>Here is all about <code>select_for_update</code> which you require to know to use in your code and to do changes to your database.</p>

<p>Cheers!</p>

<p><a href="/sandeepk/tag:Python" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">Python</span></a>
<a href="/sandeepk/tag:Django" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">Django</span></a>
<a href="/sandeepk/tag:ORM" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">ORM</span></a>
<a href="/sandeepk/tag:Database" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">Database</span></a></p>
]]></content:encoded>
      <guid>https://blogs.dgplug.org/sandeepk/django-how-to-acquire-a-lock-on-the-database-rows</guid>
      <pubDate>Sat, 14 May 2022 14:06:03 +0000</pubDate>
    </item>
    <item>
      <title>sh like infix syntax using Pipes(|) in Python</title>
      <link>https://blogs.dgplug.org/sandeepk/sh-like-infix-syntax-using-pipes-in-python</link>
      <description>&lt;![CDATA[Today, we are going to see how we can use | operator in our python code to achieve clean code. &#xA;&#xA;Here is the code where we have used map and filter for a specific operation.&#xA;In [1]: arr = [11, 12, 14, 15, 18]&#xA;In [2]: list(map(lambda x: x  2, filter(lambda x: x%2 ==1, arr)))&#xA;Out[2]: [22, 30]&#xA;The same code with Pipes.&#xA;In [1]: from pipe import select, where&#xA;In [2]: arr = [11, 12, 14, 15, 18]&#xA;In [3]: list(arr | where (lambda x: x%2 ==1) | select(lambda x:x 2))&#xA;Out[3]: [22, 30]&#xA;Pipes passes the result of one function to another function, have inbuilt pipes method like select, where, tee, traverse. &#xA;&#xA;Install Pipe&#xA;    pip install pipe&#xA;traverse&#xA;Recursively unfold iterable:&#xA; In [12]: arr = [[1,2,3], [3,4,[56]]]&#xA;In [13]: list(arr | traverse)&#xA;Out[13]: [1, 2, 3, 3, 4, 56]&#xA;select()&#xA; An alias for map().&#xA;In [1]: arr = [11, 12, 14, 15, 18]&#xA;In [2]: list(filter(lambda x: x%2 ==1, arr))&#xA;Out[2]: [11, 15]&#xA;where()&#xA;Only yields the matching items of the given iterable:&#xA;In [1]: arr = [11, 12, 14, 15, 18]&#xA;In [2]: list(arr | where(lambda x: x % 2 == 0))&#xA;Out[2]: [12, 14, 18]&#xA;sort()&#xA;Like Python&#39;s built-in &#34;sorted&#34; primitive. Allows cmp (Python 2.x&#xA;only), key, and reverse arguments. By default, sorts using the&#xA;identity function as the key.&#xA;In [1]:  &#39;&#39;.join(&#34;python&#34; | sort)&#xA;Out[1]:  &#39;hnopty&#39;&#xA;reverse&#xA;Like Python&#39;s built-in &#34;reversed&#34; primitive.&#xA;In [1]:  list([1, 2, 3] | reverse)&#xA;Out[1]:   [3, 2, 1]&#xA;strip&#xA;Like Python&#39;s strip-method for str.&#xA;In [1]:  &#39;  abc   &#39; | strip&#xA;Out[1]:  &#39;abc&#39;&#xA;&#xA;That&#39;s all for today, In this blog you have seen how to install the Pipe and use the Pipe to write clean and short code using inbuilt pipes, you can check more over here&#xA;&#xA;Cheers!&#xA;&#xA;100DaysToOffload&#xA;Python&#xA;DGPLUG]]&gt;</description>
      <content:encoded><![CDATA[<p>Today, we are going to see how we can use <em>|</em> operator in our python code to achieve clean code.</p>

<p>Here is the code where we have used map and filter for a specific operation.</p>

<pre><code class="language-python">In [1]: arr = [11, 12, 14, 15, 18]
In [2]: list(map(lambda x: x * 2, filter(lambda x: x%2 ==1, arr)))
Out[2]: [22, 30]
</code></pre>

<p>The same code with Pipes.</p>

<pre><code>In [1]: from pipe import select, where
In [2]: arr = [11, 12, 14, 15, 18]
In [3]: list(arr | where (lambda x: x%2 ==1) | select(lambda x:x *2))
Out[3]: [22, 30]
</code></pre>

<p>Pipes passes the result of one function to another function, have inbuilt pipes method like <strong>select</strong>, <strong>where</strong>, <strong>tee</strong>, <strong>traverse</strong>.</p>

<h3 id="install-pipe">Install Pipe</h3>

<pre><code class="language-shell">&gt;&gt; pip install pipe
</code></pre>

<h3 id="traverse">traverse</h3>

<p>Recursively unfold iterable:</p>

<pre><code class="language-python">In [12]: arr = [[1,2,3], [3,4,[56]]]
In [13]: list(arr | traverse)
Out[13]: [1, 2, 3, 3, 4, 56]
</code></pre>

<h3 id="select">select()</h3>

<p> An alias for map().</p>

<pre><code class="language-python">In [1]: arr = [11, 12, 14, 15, 18]
In [2]: list(filter(lambda x: x%2 ==1, arr))
Out[2]: [11, 15]
</code></pre>

<h3 id="where">where()</h3>

<p>Only yields the matching items of the given iterable:</p>

<pre><code class="language-python">In [1]: arr = [11, 12, 14, 15, 18]
In [2]: list(arr | where(lambda x: x % 2 == 0))
Out[2]: [12, 14, 18]
</code></pre>

<h3 id="sort">sort()</h3>

<p>Like Python&#39;s built-in “sorted” primitive. Allows cmp (Python 2.x
only), key, and reverse arguments. By default, sorts using the
identity function as the key.</p>

<pre><code class="language-python">In [1]:  &#39;&#39;.join(&#34;python&#34; | sort)
Out[1]:  &#39;hnopty&#39;
</code></pre>

<h3 id="reverse">reverse</h3>

<p>Like Python&#39;s built-in “reversed” primitive.</p>

<pre><code class="language-python">In [1]:  list([1, 2, 3] | reverse)
Out[1]:   [3, 2, 1]
</code></pre>

<h3 id="strip">strip</h3>

<p>Like Python&#39;s strip-method for str.</p>

<pre><code class="language-python">In [1]:  &#39;  abc   &#39; | strip
Out[1]:  &#39;abc&#39;
</code></pre>

<p>That&#39;s all for today, In this blog you have seen how to install the Pipe and use the Pipe to write clean and short code using inbuilt pipes, you can check more over <a href="https://github.com/JulienPalard/Pipe#existing-pipes-in-this-module" rel="nofollow">here</a></p>

<p>Cheers!</p>

<p><a href="/sandeepk/tag:100DaysToOffload" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">100DaysToOffload</span></a>
<a href="/sandeepk/tag:Python" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">Python</span></a>
<a href="/sandeepk/tag:DGPLUG" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">DGPLUG</span></a></p>
]]></content:encoded>
      <guid>https://blogs.dgplug.org/sandeepk/sh-like-infix-syntax-using-pipes-in-python</guid>
      <pubDate>Mon, 29 Nov 2021 14:18:04 +0000</pubDate>
    </item>
    <item>
      <title>Profiling Django Application</title>
      <link>https://blogs.dgplug.org/sandeepk/profiling-django-application</link>
      <description>&lt;![CDATA[My work required me to profile one of our Django applications, to help identify the point in the application which we can improve to reach our North Star. So, I thought it will be great to share my learning and tools, that I have used to get the job done.&#xA;&#xA;What is Profiling?&#xA;Profiling) is a measure of the time or memory consumption of the running program. This data further can be used for program optimization.&#xA;&#xA;They are many tools/libraries out there which can be used to do the job. I have found these helpful.&#xA;&#xA;Apache JMeter&#xA;It is open-source software, which is great to load and performance test web applications. It&#39;s easy to set up and can be configured for what we want in the result report.&#xA;&#xA;Pyinstrument&#xA;Pyinstrument is a Python profiler that offers a Django middleware to record the profiling. The profiler generates profile data for every request. The PYINSTRUMENTPROFILEDIR contains a directory that stores the profile data, which is in HTML format. You can check how it works over here&#xA;&#xA;Django Query Count&#xA;Django Query Count is a middleware that prints the number of database queries made during the request processing. There are two possible settings for this, which can be found here&#xA;&#xA;Django Silk&#xA;Django Silk is middleware for intercepting Requests/Responses. We can profile a block of code or functions, either manually or dynamically. It also has a user interface for inspection and visualization &#xA;&#xA;So, here are some of the tools which can be of great help in profiling your code and putting your effort in the right direction of optimization applications.&#xA;&#xA;Cheers!&#xA;&#xA;100DaysToOffload&#xA;Python&#xA;DGPLUG&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>My work required me to profile one of our Django applications, to help identify the point in the application which we can improve to reach our North Star. So, I thought it will be great to share my learning and tools, that I have used to get the job done.</p>

<h2 id="what-is-profiling">What is Profiling?</h2>

<p><a href="https://en.wikipedia.org/wiki/Profiling_(computer_programming)" rel="nofollow">Profiling</a> is a measure of the time or memory consumption of the running program. This data further can be used for program optimization.</p>

<p>They are many tools/libraries out there which can be used to do the job. I have found these helpful.</p>

<h2 id="apache-jmeter-https-jmeter-apache-org"><a href="https://jmeter.apache.org/" rel="nofollow">Apache JMeter</a></h2>

<p>It is open-source software, which is great to load and performance test web applications. It&#39;s easy to set up and can be configured for what we want in the result report.</p>

<h2 id="pyinstrument-https-pyinstrument-readthedocs-io-en-latest-home-html"><a href="https://pyinstrument.readthedocs.io/en/latest/home.html" rel="nofollow">Pyinstrument</a></h2>

<p>Pyinstrument is a Python profiler that offers a Django middleware to record the profiling. The profiler generates profile data for every request. The PYINSTRUMENT<em>PROFILE</em>DIR contains a directory that stores the profile data, which is in HTML format. You can check how it works over <a href="https://pyinstrument.readthedocs.io/en/latest/how-it-works.html" rel="nofollow">here</a></p>

<h2 id="django-query-count-https-github-com-bradmontgomery-django-querycount"><a href="https://github.com/bradmontgomery/django-querycount" rel="nofollow">Django Query Count</a></h2>

<p>Django Query Count is a middleware that prints the number of database queries made during the request processing. There are two possible settings for this, which can be found <a href="https://github.com/bradmontgomery/django-querycount#settings" rel="nofollow">here</a></p>

<h2 id="django-silk-https-github-com-jazzband-django-silk"><a href="https://github.com/jazzband/django-silk" rel="nofollow">Django Silk</a></h2>

<p>Django Silk is middleware for intercepting Requests/Responses. We can profile a block of code or functions, either manually or dynamically. It also has a user interface for inspection and visualization</p>

<p>So, here are some of the tools which can be of great help in profiling your code and putting your effort in the right direction of optimization applications.</p>

<p>Cheers!</p>

<p><a href="/sandeepk/tag:100DaysToOffload" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">100DaysToOffload</span></a>
<a href="/sandeepk/tag:Python" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">Python</span></a>
<a href="/sandeepk/tag:DGPLUG" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">DGPLUG</span></a></p>
]]></content:encoded>
      <guid>https://blogs.dgplug.org/sandeepk/profiling-django-application</guid>
      <pubDate>Sun, 28 Nov 2021 12:00:31 +0000</pubDate>
    </item>
  </channel>
</rss>