<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kanak Tanwar</title>
    <description>The latest articles on DEV Community by Kanak Tanwar (@kanakos01).</description>
    <link>https://dev.to/kanakos01</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2678486%2F8f6b039b-a853-4e36-b1e2-a6f174c2b57a.png</url>
      <title>DEV Community: Kanak Tanwar</title>
      <link>https://dev.to/kanakos01</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kanakos01"/>
    <language>en</language>
    <item>
      <title>reducing memory cost of boolean in python</title>
      <dc:creator>Kanak Tanwar</dc:creator>
      <pubDate>Fri, 13 Feb 2026 11:00:03 +0000</pubDate>
      <link>https://dev.to/kanakos01/reducing-memory-cost-of-boolean-in-python-2lio</link>
      <guid>https://dev.to/kanakos01/reducing-memory-cost-of-boolean-in-python-2lio</guid>
      <description>&lt;p&gt;while scrolling through twitter i came across a tweet about how python boolean variable takes up 192 bits. this was new to me, i had never really thought about how much space python variables actually take(if this was a concern i should not have been using python at all).&lt;/p&gt;

&lt;p&gt;so i researched it a bit and though it wasn't entirely correct, it wasn't entirely wrong either (explanation below). this prompted me into looking more into how bools are represented in python and how (possibly using underhanded means) can we reduce the space taken by booleans.&lt;/p&gt;




&lt;h2&gt;
  
  
  booleans in python
&lt;/h2&gt;

&lt;p&gt;booleans are simple. just 2 values - TRUE or FALSE. theoretically they can be represented by just 1 bit (0 or 1).&lt;/p&gt;

&lt;p&gt;so why does python use 192 bits (on 32 bit systems) and 224 bits (on 64 bit systems)?&lt;/p&gt;

&lt;p&gt;the &lt;code&gt;True&lt;/code&gt; and &lt;code&gt;False&lt;/code&gt; values in cpython are not primitives, but a python object (a subclass of int actually, which is also a python object and not a primitive).&lt;br&gt;
the catch however is that the &lt;code&gt;bool&lt;/code&gt; class is a singleton class (there exists only a single object which is shared by all the references)&lt;br&gt;
this means that the 28 byte size is actually just paid once. apart from this constant cost however, we use an extra 8 bytes used by pointer references to the &lt;code&gt;bool&lt;/code&gt; objects.&lt;/p&gt;




&lt;h2&gt;
  
  
  how small can booleans get
&lt;/h2&gt;

&lt;p&gt;now that we have established that storing a boolean inside a container in CPython costs ~8 bytes per value due to pointer references, let us see how low we can go.&lt;/p&gt;

&lt;p&gt;the theoritical limit will obviously be 1 bit (0 or 1), so let's try to reach that benchmark&lt;/p&gt;




&lt;h2&gt;
  
  
  results
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;i have measured most of the sizes by taking average over a list of values as that is what gives the actual image of how large the data is after removing the constant overhead&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Representation&lt;/th&gt;
&lt;th&gt;Storage cost per boolean (approx)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Python &lt;code&gt;bool&lt;/code&gt; (in list/container)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;8 bytes&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bytearray&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1 byte&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;int&lt;/code&gt; bitset&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~0.13 bytes (~1.05 bits)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  bool datatype (baseline)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F234ipn97ktny500a3jdg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F234ipn97ktny500a3jdg.png" alt="bool var image" width="800" height="116"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;True&lt;/code&gt; (or &lt;code&gt;False&lt;/code&gt;) singleton object is of size 28 bytes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhnkz6gq47kn12teg3df5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhnkz6gq47kn12teg3df5.png" alt="bool list image" width="800" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;a pointer to bool objects take 8 bytes of space. so the average value of using bool in python is ~8 bytes.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  bytearray
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;bytearray&lt;/code&gt; in python allows us to storing raw bytes. so the smallest unit in a bytearray takes up only 1 byte.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjyuotcs2p2ig0z59u53e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjyuotcs2p2ig0z59u53e.png" alt="bytearray image" width="800" height="115"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  bitset (kind of)
&lt;/h3&gt;

&lt;p&gt;python does not have bitset like c++, but we can use int as a replacement. python int range is not fixed, so we can have a large number of bits.&lt;/p&gt;

&lt;p&gt;True and False can be represented by 1 and 0 in an integer like &lt;code&gt;0b110100101&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;the amortized cost of per bit when using int comes out to be ~0.13 bytes = ~1.05 bit (pretty close to the theoretical minimum)&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbvc4rmzdxcgsl9xtfwq1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbvc4rmzdxcgsl9xtfwq1.png" alt="biset image" width="800" height="131"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  conclusion
&lt;/h2&gt;

&lt;p&gt;python isn’t designed for memory-dense primitives, but with a little bit of abuse you can get surprisingly close to the theoretical 1-bit limit.&lt;/p&gt;

&lt;p&gt;should you do this in real code? probably not. if something like this is a concern you shoudln't be using python at all :).&lt;br&gt;
but if you still do, here's how you can take advantage of it.&lt;/p&gt;




</description>
      <category>python</category>
      <category>programming</category>
    </item>
    <item>
      <title>REST Pagination techniques</title>
      <dc:creator>Kanak Tanwar</dc:creator>
      <pubDate>Sun, 05 Oct 2025 07:13:40 +0000</pubDate>
      <link>https://dev.to/kanakos01/rest-pagination-techniques-p9b</link>
      <guid>https://dev.to/kanakos01/rest-pagination-techniques-p9b</guid>
      <description>&lt;p&gt;My thoughts had always been that pagination was straightforward — just throw in a &lt;code&gt;LIMIT&lt;/code&gt; and &lt;code&gt;OFFSET&lt;/code&gt; and you’re good to go. But recently, I got to know that there are different pagination techniques, some more efficient, some used for a specific use case. And so I thought of writing about them, along with code a rudimentary code implementation in FastAPI and some benchmarks of their performance.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;The code can be found &lt;a href="https://github.com/kanakOS01/pagination" rel="noopener noreferrer"&gt;https://github.com/kanakOS01/pagination&lt;/a&gt;.&lt;br&gt;
The instructions for running the code are in the repo itself. If you find it helpful a star would be great.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Among the different types of pagination I found online (offset, page, cursor, keyset etc), we can broadly classify pagination into 2 categories&lt;/p&gt;

&lt;h2&gt;
  
  
  Offset Pagination
&lt;/h2&gt;

&lt;p&gt;Offset pagination is the most common form. It’s the classic &lt;code&gt;LIMIT&lt;/code&gt;/&lt;code&gt;OFFSET&lt;/code&gt; approach:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="k"&gt;data&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;
&lt;span class="k"&gt;OFFSET&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple to implement.&lt;/li&gt;
&lt;li&gt;Great for small datasets.&lt;/li&gt;
&lt;li&gt;Supports “jump to page X.”&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Slow for large offsets (e.g., OFFSET 1M).&lt;/li&gt;
&lt;li&gt;Can cause inconsistent results if data changes between requests.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h3&gt;
  
  
  Page Pagination
&lt;/h3&gt;

&lt;p&gt;Page pagination is just a wrapper around offset. Instead of &lt;code&gt;offset=1000&lt;/code&gt;, you say &lt;code&gt;page=100&lt;/code&gt; with &lt;code&gt;page_size=10&lt;/code&gt;, and the system translates it into an offset internally.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="k"&gt;data&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;
&lt;span class="k"&gt;OFFSET&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&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="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;page_size&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="n"&gt;page_size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Familiar and user-friendly.&lt;/li&gt;
&lt;li&gt;Easier UX for users who want to jump to a specific page.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Same performance problems as offset.&lt;/li&gt;
&lt;li&gt;Still prone to data inconsistency with inserts/deletes.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Cursor Pagination
&lt;/h2&gt;

&lt;p&gt;Cursor pagination uses a known column value as an anchor (like &lt;code&gt;id&lt;/code&gt; or &lt;code&gt;created_at&lt;/code&gt;) instead of a raw offset.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;pagination_dataset&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cursor_id&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Super efficient — no scanning and discarding rows.&lt;/li&gt;
&lt;li&gt;Scales well for large datasets.&lt;/li&gt;
&lt;li&gt;Great for sequential or immutable data (logs, feeds).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No direct “jump to page 100.”&lt;/li&gt;
&lt;li&gt;Exposes database internals (like IDs) if not wrapped.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This is the approach used by modern APIs like GitHub, Twitter, and Facebook.&lt;/p&gt;




&lt;h3&gt;
  
  
  Keyset Pagination
&lt;/h3&gt;

&lt;p&gt;I could not find much difference between keyset and cursor pagination. The idea for both of them is the same (like offset and page). One difference would be that cursor pagination returns a cursor like object (encoded by the application code), this prevents leaking information through endpoints. This however also introduces minor overhead.&lt;/p&gt;




&lt;h2&gt;
  
  
  Benchmarking
&lt;/h2&gt;

&lt;p&gt;So, I thought it would be fun to benchmark these approaches myself to verify the results I had in my mind (there are a number of benchmarks and comparisons available on the net already but I thought why not just do it again :)).&lt;/p&gt;

&lt;p&gt;So I made a simple script (available in the github repo mentioned at the top) to benchmark offset and cursor pagination. And here are the results.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fss0j2wquqd4cqxo0agy7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fss0j2wquqd4cqxo0agy7.png" alt="Cursor vs Offset pagination" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;offset/page pagination&lt;/strong&gt; for small datasets or cases where “jump to page X” is important.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;keyset or cursor pagination&lt;/strong&gt; for large datasets, APIs, and infinite scroll use cases.&lt;/li&gt;
&lt;li&gt;If you’re building a public API, &lt;strong&gt;cursor pagination&lt;/strong&gt; is the way to go.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pagination might look trivial at first, but at scale, the right choice can save you massive performance headaches.&lt;/p&gt;




</description>
      <category>fastapi</category>
      <category>pagination</category>
      <category>restapi</category>
      <category>python</category>
    </item>
    <item>
      <title>Benchmarking python JSON libraries</title>
      <dc:creator>Kanak Tanwar</dc:creator>
      <pubDate>Thu, 24 Jul 2025 15:08:39 +0000</pubDate>
      <link>https://dev.to/kanakos01/benchmarking-python-json-libraries-33bb</link>
      <guid>https://dev.to/kanakos01/benchmarking-python-json-libraries-33bb</guid>
      <description>&lt;p&gt;While reading the FastAPI documentation I came across various python libraries for working with &lt;code&gt;json&lt;/code&gt;. This got me thinking which one is the best, performance wise (including the python's built-in json module).&lt;/p&gt;

&lt;p&gt;I surfed the net, found some resources and comparisions, and thought of implementing them on my own. So, this article is about the perf benchmarks I got when testing these libraries and the methodology.&lt;/p&gt;




&lt;h2&gt;
  
  
  Test Setup
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ubuntu 24.04 LTS&lt;/li&gt;
&lt;li&gt;RAM - 24 GB&lt;/li&gt;
&lt;li&gt;Python version - 3.12&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Libraries tested
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.python.org/3/library/json.html" rel="noopener noreferrer"&gt;&lt;code&gt;json&lt;/code&gt;&lt;/a&gt; - Built-in Python JSON library; widely used but relatively slow.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pypi.org/project/ujson/" rel="noopener noreferrer"&gt;&lt;code&gt;ujson&lt;/code&gt;&lt;/a&gt; - Fast C-based JSON parser; a drop-in replacement for json.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pypi.org/project/orjson/2.0.1/" rel="noopener noreferrer"&gt;&lt;code&gt;orjson&lt;/code&gt;&lt;/a&gt; - Extremely fast Rust-based library with rich type support.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pypi.org/project/python-rapidjson/" rel="noopener noreferrer"&gt;&lt;code&gt;rapidjson&lt;/code&gt;&lt;/a&gt; - Python wrapper for RapidJSON (C++); good performance and flexibility.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pypi.org/project/msgspec/" rel="noopener noreferrer"&gt;&lt;code&gt;msgspec&lt;/code&gt;&lt;/a&gt; - Ultra-fast library with optional typed structs for maximum speed.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Library&lt;/th&gt;
&lt;th&gt;Serialization Time (s)&lt;/th&gt;
&lt;th&gt;Deserialization Time (s)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;json&lt;/td&gt;
&lt;td&gt;1.616786&lt;/td&gt;
&lt;td&gt;1.616203&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ujson&lt;/td&gt;
&lt;td&gt;1.413367&lt;/td&gt;
&lt;td&gt;1.853332&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;orjson&lt;/td&gt;
&lt;td&gt;0.417962&lt;/td&gt;
&lt;td&gt;1.272813&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rapidjson&lt;/td&gt;
&lt;td&gt;2.044958&lt;/td&gt;
&lt;td&gt;1.717067&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;msgspec&lt;/td&gt;
&lt;td&gt;0.489964&lt;/td&gt;
&lt;td&gt;0.930834&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpy1bt89uxwg4zaruy7wv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpy1bt89uxwg4zaruy7wv.png" alt="Bargraph for perf benchmarks" width="800" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Takeways&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The top contendors are &lt;code&gt;orjson&lt;/code&gt; and &lt;code&gt;msgspec&lt;/code&gt; (duh).&lt;/li&gt;
&lt;li&gt;I personally like to use orjson when working with fastAPI as it has builtin support for orjson response format making it a more developer friendly option.&lt;/li&gt;
&lt;li&gt;msgspec on the other hand is like a swiss army knife as it has support for other structs as well like &lt;code&gt;yaml&lt;/code&gt;, &lt;code&gt;toml&lt;/code&gt; etc. And it has a ton of more validation features like validating with a python class (sort of like pydantic).&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Methodology
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Generating sample data
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;A simple script to generate the testing data (can be made complex for better benchmarking).&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_sample_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;active&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;scores&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;info&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;age&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;city&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;City&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_sample_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10_000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Benchmarking function
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Store the encoding and decoding methods of every library in a dictionary with the lib names as the key and run this function.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;benchmark_json_libs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="c1"&gt;# Pre-serialize data for each lib
&lt;/span&gt;    &lt;span class="n"&gt;pre_serialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;funcs&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;libs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;pre_serialized&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;funcs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dumps&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Serialization failed for &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;funcs&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;libs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pre_serialized&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;

        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;ser_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;funcs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dumps&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;deser_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;funcs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;loads&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;pre_serialized&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Library&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Serialization Time (s)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ser_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Deserialization Time (s)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;deser_time&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Benchmarking failed for &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Visualization
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Visualize the result using seaborn and matplotlib.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;fig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;axes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subplots&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;figsize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;sns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;barplot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Library&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Serialization Time (s)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;results_df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ax&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;axes&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;axes&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="nf"&gt;set_title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;JSON Serialization Time&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;sns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;barplot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Library&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Deserialization Time (s)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;results_df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ax&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;axes&lt;/span&gt;&lt;span class="p"&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;axes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;set_title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;JSON Deserialization Time&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tight_layout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;And that's it. Thanks for reading. Bye.&lt;/p&gt;

</description>
      <category>python</category>
      <category>json</category>
      <category>programming</category>
    </item>
    <item>
      <title>Automation | A Developer's Personal Assisstant with Runner H</title>
      <dc:creator>Kanak Tanwar</dc:creator>
      <pubDate>Sun, 06 Jul 2025 07:02:56 +0000</pubDate>
      <link>https://dev.to/kanakos01/automation-a-developers-personal-assisstant-with-runner-h-57gj</link>
      <guid>https://dev.to/kanakos01/automation-a-developers-personal-assisstant-with-runner-h-57gj</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/runnerh"&gt;Runner H "AI Agent Prompting" Challenge&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
This is a submission for the Runner H "AI Agent Prompting" Challenge&lt;/p&gt;


&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;As part of the Runner H AI Agent Prompting Challenge, I built a virtual personal assistant workflow tailored for developers like myself. This AI-powered assistant handles a curated set of daily non-technical tasks — from scanning Hacker News and Product Hunt for updates, to checking my Google Calendar and even sending me a motivational nudge.&lt;/p&gt;

&lt;p&gt;This assistant helps developers stay informed, organized, and inspired — without lifting a finger.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Think of this as a template of what the assisstant can do and can be easily finetuned according to everyone's need.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;The run of the task can be found &lt;a href="https://runner.hcompany.ai/chat/007bf5b2-e75d-4426-aa40-1cb00e27bb98/share" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And some snapshots of the output are here -&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fppfk2zmiu11nwl1xat9h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fppfk2zmiu11nwl1xat9h.png" alt="Completed tasks"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnpj5aczt2htkd0c5xs8p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnpj5aczt2htkd0c5xs8p.png" alt="News Digest"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqt7i3ggb7xdocckru2d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqt7i3ggb7xdocckru2d.png" alt="Product Hunt"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  How I Used Runner H
&lt;/h2&gt;

&lt;p&gt;I created a custom prompt that instructs Runner H to complete four tasks each day, mimicking the flow of a helpful executive assistant. This required external tool calling and connections, specifically &lt;code&gt;google calendar&lt;/code&gt;, &lt;code&gt;gmail&lt;/code&gt; and &lt;code&gt;google docs&lt;/code&gt; Here's how it breaks down:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Task 1: News Digest&lt;/strong&gt;&lt;br&gt;
Runner H visits Hacker News and scrapes the latest articles and threads related to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI&lt;/li&gt;
&lt;li&gt;Startups&lt;/li&gt;
&lt;li&gt;Open Source Software&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It then generates summaries for each relevant post, adds the original URLs, and neatly organizes everything into a Google Doc titled News Digest [Date]. This keeps me updated without doomscrolling through the HN front page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Task 2: Product Hunt Highlights&lt;/strong&gt;&lt;br&gt;
Runner H checks Product Hunt for top products from yesterday.&lt;br&gt;
It then:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Summarizes the general trends and categories of the products launched.&lt;/li&gt;
&lt;li&gt;Highlights standout tools or startups showing technical innovation.&lt;/li&gt;
&lt;li&gt;Compiles the results in a doc titled Product Hunt [Date].&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is my shortcut to understanding what's new in the product ecosystem — ideal for inspiration and trend tracking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Task 3: Calendar Check&lt;/strong&gt;&lt;br&gt;
Runner H connects to my Google Calendar and:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lists all scheduled meetings or events for the day.&lt;/li&gt;
&lt;li&gt;Alerts me about any special occasions (birthdays, holidays, etc.).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This daily briefing helps me stay prepared and avoid surprises during the workday.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Task 4: Motivation Check&lt;/strong&gt;&lt;br&gt;
To keep morale high, Runner H sends me a motivational quote during the second half of the day. This small but meaningful gesture provides a mental reset and helps me push through the afternoon dip.&lt;/p&gt;


&lt;h2&gt;
  
  
  Real-World Impact:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Time Saved: I avoid 30–60 minutes of daily manual browsing across HN, Product Hunt, and email/calendar platforms.&lt;/li&gt;
&lt;li&gt;Better Focus: No more tab overload. Everything is delivered in one place.&lt;/li&gt;
&lt;li&gt;Motivation Boost: A mid-day quote might sound small, but it helps me reset when energy dips.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  The Prompt
&lt;/h2&gt;

&lt;p&gt;Here’s the full prompt I used to power this personal assistant via Runner H:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are to complete the following tasks as my personal assistant.

## Task 1 - News Digest
Go to https://news.ycombinator.com/ and find articles, threads and blogs on AI, Startup and Open Source Software. Generate a summary for all the relevant items that you find and put them in a google docs along with the original url to the post. Organize the summaries into a google doc named `News Digest [Today's date]`.

## Task 2 - Product Hunt
Go to product hunt and find the top products of yesterday. Give a summary of the overall intent of the products, their domains and some products that stood out of the rest in terms of technical innovation. Report this in a google doc named `Product Hunt [Today's date]`.

## Task 3 - Calendar Check
Check my google calendar for any meetings or events that I have planned for today. Also give a reminder if there is any occasion planned for today.

## Task 4 - Motivation Check
Send me a motivational quote in the latter half of the day to keep me going with my work.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Socials
&lt;/h2&gt;

&lt;p&gt;Shared on Twitter/X and LinkedIn links below:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1941756502064136626-193" src="https://platform.twitter.com/embed/Tweet.html?id=1941756502064136626"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1941756502064136626-193');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1941756502064136626&amp;amp;theme=dark"
  }



&lt;br&gt;
&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://www.linkedin.com/posts/kanak-tanwar_automation-a-developers-personal-assisstant-activity-7347521676554735616-r7un?utm_source=social_share_send&amp;amp;amp%3Butm_medium=member_desktop_web&amp;amp;amp%3Brcm=ACoAAD3hMswBI-ctlghS8HwwZgwOURWa8CDLv1E" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.licdn.com%2Fdms%2Fimage%2Fsync%2Fv2%2FD5627AQFx3VF1UrNuXw%2Farticleshare-shrink_1280_800%2FB56ZfekBILG0AQ-%2F0%2F1751785674579%3Fe%3D2147483647%26v%3Dbeta%26t%3Dn0MY3OBA76jNTefkYxRKjFca9aOoRzFcO8FwXOA3D48" height="auto" class="m-0"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://www.linkedin.com/posts/kanak-tanwar_automation-a-developers-personal-assisstant-activity-7347521676554735616-r7un?utm_source=social_share_send&amp;amp;amp%3Butm_medium=member_desktop_web&amp;amp;amp%3Brcm=ACoAAD3hMswBI-ctlghS8HwwZgwOURWa8CDLv1E" rel="noopener noreferrer" class="c-link"&gt;
            Automation | A Developer's Personal Assisstant with Runner H | Kanak Tanwar
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            https://lnkd.in/gjvi7b8b
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstatic.licdn.com%2Faero-v1%2Fsc%2Fh%2Fal2o9zrvru7aqj8e1x2rzsrca"&gt;
          linkedin.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;






&lt;p&gt;That's all from me today. Thanks.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>runnerhchallenge</category>
      <category>ai</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Using MindsDB to create a smart email CLI client</title>
      <dc:creator>Kanak Tanwar</dc:creator>
      <pubDate>Mon, 30 Jun 2025 17:53:15 +0000</pubDate>
      <link>https://dev.to/kanakos01/using-mindsdb-to-create-a-smart-email-cli-client-1b8o</link>
      <guid>https://dev.to/kanakos01/using-mindsdb-to-create-a-smart-email-cli-client-1b8o</guid>
      <description>&lt;h2&gt;
  
  
  Building an AI-powered Semantic Email Search in Your Terminal
&lt;/h2&gt;

&lt;p&gt;So, a new quest came out on &lt;a href="https://quira.sh/quests/creator/details?questId=19" rel="noopener noreferrer"&gt;quira&lt;/a&gt; in which we had to make something using MindsDB Knowledge Bases. As I read through the description it struck to me that a semantic powered email client would be a great thing to work on. It would hit off all the required points while also having some actual irl usecase.&lt;/p&gt;

&lt;p&gt;And so i made &lt;strong&gt;grepmail&lt;/strong&gt;: a terminal-based CLI app that lets you semantically search your inbox using natural language queries. It uses MindsDB, PGVector, Gemini, and ollama to turn your mailbox into an AI-searchable database.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It’s like &lt;code&gt;grep&lt;/code&gt; for your email—but smart.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://github.com/kanakOS01/grepMail" rel="noopener noreferrer"&gt;Here is the grepMail github repo&lt;/a&gt; incase you want to go through the code. The code is decently large so i won't be able to explain everything in the article itself.&lt;/p&gt;







&lt;h3&gt;
  
  
  What grepmail Can Do
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Search your email inbox semantically using plain English&lt;/li&gt;
&lt;li&gt;Sync with IMAP mailboxes (Gmail, Outlook, etc.)&lt;/li&gt;
&lt;li&gt;Store vectorized email content in Postgres via PGVector&lt;/li&gt;
&lt;li&gt;Use LLMs (Gemini, Ollama) for embedding and querying&lt;/li&gt;
&lt;li&gt;Display results in a clean, rich terminal UI&lt;/li&gt;
&lt;/ul&gt;







&lt;h2&gt;
  
  
  ⚙️ Tech Stack Overview
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Part&lt;/th&gt;
&lt;th&gt;Tech&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CLI&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://typer.tiangolo.com/" rel="noopener noreferrer"&gt;Typer&lt;/a&gt;, &lt;a href="https://github.com/Textualize/rich" rel="noopener noreferrer"&gt;Rich&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LLM&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://ollama.com" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt;, &lt;code&gt;nomic-embed-text&lt;/code&gt;, Gemini&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Email Access&lt;/td&gt;
&lt;td&gt;IMAP via &lt;a href="https://docs.mindsdb.com/integrations/app-integrations/email#email" rel="noopener noreferrer"&gt;MindsDB Email Engine&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vector DB&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/pgvector/pgvector" rel="noopener noreferrer"&gt;PGVector&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Orchestration&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.mindsdb.com/mindsdb_sql/knowledge-bases" rel="noopener noreferrer"&gt;MindsDB Knowledge Base&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Packaging&lt;/td&gt;
&lt;td&gt;&lt;a href="https://python-poetry.org/" rel="noopener noreferrer"&gt;Poetry&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;







&lt;h3&gt;
  
  
  File structure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── grepmail
│   ├── __init__.py
│   ├── logger.py
│   ├── main.py
│   ├── mindsdb
│   ├── handlers
│   │   ├── common.py
│   │   ├── email.py
│   │   └── __init__.py
│   └── main.py
├── grepmail.log
├── handlers.txt
├── LICENSE
├── poetry.lock
├── pyproject.toml
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The main parts to keep notice of are - &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;grepmail/main.py&lt;/code&gt; - the cli&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;grepmail/handlers/common.py&lt;/code&gt; - functions for some common tasks&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;grepmail/handlers/email.py&lt;/code&gt; - functions for email related tasks&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;







&lt;h3&gt;
  
  
  Major Components
&lt;/h3&gt;




&lt;p&gt;As i said i wont be going through the entire code but rather the main parts of the system. Connecting these together is a pretty trivial task.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Email Access with MindsDB Email Engine
&lt;/h4&gt;

&lt;p&gt;You can access you email account with the &lt;a href="https://docs.mindsdb.com/integrations/app-integrations/email" rel="noopener noreferrer"&gt;MindsDB Email Integration&lt;/a&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  2. Vectorizing Emails with Ollama
&lt;/h4&gt;

&lt;p&gt;I used &lt;code&gt;nomic-embed-text&lt;/code&gt; for generating vector embeddings locally. With Ollama, it was as easy as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama pull nomic-embed-text
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then, when loading emails for the first time, grepmail chunks and vectorizes each one, storing them in the PGVector store.&lt;/p&gt;




&lt;h4&gt;
  
  
  3. Setting Up PGVector for Storage
&lt;/h4&gt;

&lt;p&gt;Emails are heavy, so I wanted a fast and efficient vector store. MindsDB has an integration with &lt;a href="https://docs.mindsdb.com/integrations/vector-db-integrations/pgvector#pgvector" rel="noopener noreferrer"&gt;PGVector&lt;/a&gt;, and I used that to store and search through embeddings efficiently.&lt;/p&gt;




&lt;h4&gt;
  
  
  4. MindsDB Knowledge Base for Semantic Search
&lt;/h4&gt;

&lt;p&gt;Here’s where the magic happens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Store email content as vector chunks&lt;/li&gt;
&lt;li&gt;Index them via &lt;code&gt;CREATE INDEX&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Query using natural language like this:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;email_kb&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'flight confirmation from last week'&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s literally it.&lt;/p&gt;




&lt;h4&gt;
  
  
  5. Local Caching for Speed
&lt;/h4&gt;

&lt;p&gt;The first time you run grepmail, it loads all your emails into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MindsDB’s knowledge base&lt;/li&gt;
&lt;li&gt;A local Postgres DB (so future queries are instant)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This took some engineering because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IMAP servers are &lt;strong&gt;slow&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Ollama runs one model instance at a time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I had to skip concurrency for now (sorry 🫠), but the system is built to handle these steps incrementally and linearly.&lt;/p&gt;




&lt;h4&gt;
  
  
  6. CLI Experience with Typer + Rich
&lt;/h4&gt;

&lt;p&gt;I wanted this tool to feel smooth in the terminal. Typer gave me auto-generated help menus and clean argument parsing. Rich handled beautiful tables, syntax highlighting, and progress bars.&lt;/p&gt;




&lt;h4&gt;
  
  
  7. Syncing Emails
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://docs.mindsdb.com/generative-ai-tables#generative-ai-tables" rel="noopener noreferrer"&gt;https://docs.mindsdb.com/generative-ai-tables#generative-ai-tables&lt;/a&gt;.&lt;br&gt;
Another important task to be done is syncing emails to the local db and knowledge base. MindsDB has a builtin in &lt;a href="https://docs.mindsdb.com/mindsdb_sql/sql/create/jobs#jobs" rel="noopener noreferrer"&gt;Jobs&lt;/a&gt; module which helped in fetching the email from the server every hour without any deep technical work.&lt;/p&gt;

&lt;h4&gt;
  
  
  8. Summarizing Emails
&lt;/h4&gt;

&lt;p&gt;Another nice quirk i added was to create an &lt;a href="https://docs.mindsdb.com/generative-ai-tables#generative-ai-tables" rel="noopener noreferrer"&gt;AI table / model&lt;/a&gt; which would summarize my email content into a few lines ;))&lt;/p&gt;







&lt;p&gt;That's it from my side. The architecture is pretty simple and going through the MindsDB docs you will be able to replicated this kind of application yourself.&lt;/p&gt;

</description>
      <category>mindsdb</category>
      <category>ai</category>
      <category>python</category>
      <category>quira</category>
    </item>
    <item>
      <title>Managing Python Deps with Poetry</title>
      <dc:creator>Kanak Tanwar</dc:creator>
      <pubDate>Thu, 27 Feb 2025 07:46:19 +0000</pubDate>
      <link>https://dev.to/kanakos01/managing-python-deps-with-poetry-4l38</link>
      <guid>https://dev.to/kanakos01/managing-python-deps-with-poetry-4l38</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Managing dependencies in Python projects can often become cumbersome, especially as projects grow in complexity. &lt;a href="https://python-poetry.org/" rel="noopener noreferrer"&gt;&lt;strong&gt;Poetry&lt;/strong&gt;&lt;/a&gt; is a modern dependency management and packaging tool that simplifies this process, offering a streamlined way to create, manage, and distribute Python projects.&lt;/p&gt;



&lt;h2&gt;
  
  
  Use Cases
&lt;/h2&gt;

&lt;p&gt;Poetry offers several advantages over traditional dependency managers like &lt;code&gt;pip&lt;/code&gt; and &lt;code&gt;venv&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;1) &lt;strong&gt;Simplified Dependency Management&lt;/strong&gt;: Unlike &lt;code&gt;requirements.txt&lt;/code&gt;, Poetry uses a &lt;code&gt;pyproject.toml&lt;/code&gt; file to handle dependencies more effectively.&lt;/p&gt;

&lt;p&gt;2) &lt;strong&gt;Automatic Virtual Environments&lt;/strong&gt;: Poetry automatically creates and manages virtual environments for your projects.&lt;/p&gt;

&lt;p&gt;3) &lt;strong&gt;Semantic Versioning&lt;/strong&gt;: It ensures that dependencies adhere to semantic versioning, reducing compatibility issues.&lt;/p&gt;

&lt;p&gt;4) &lt;strong&gt;Publishing Made Easy&lt;/strong&gt;: With a single command, you can publish your package to PyPI.&lt;/p&gt;

&lt;p&gt;Although there are a lot of use cases, in this article we will focus on how to setup a project with poetry and manage its dependencies.&lt;/p&gt;



&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;The easiest way to do this is to use &lt;a href="https://pipx.pypa.io/stable/" rel="noopener noreferrer"&gt;pipx&lt;/a&gt; as it installs packages in an isolated environment.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you don't have poetry install you can insatll it from &lt;a href="https://pipx.pypa.io/stable/installation/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pipx &lt;span class="nb"&gt;install &lt;/span&gt;poetry
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;There are other methods of installation listed &lt;a href="https://python-poetry.org/docs/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h2&gt;
  
  
  Project Setup
&lt;/h2&gt;

&lt;p&gt;There are a few ways to setup your project with poetry.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://python-poetry.org/docs/basic-usage/" rel="noopener noreferrer"&gt;official poetry documentation&lt;/a&gt; it is recommended to use &lt;code&gt;poetry new &amp;lt;project-name&amp;gt;&lt;/code&gt;. This creates a folder with the name of the project and creates some boilerplate which include a &lt;code&gt;README.md&lt;/code&gt;, &lt;code&gt;src&lt;/code&gt;, &lt;code&gt;tests&lt;/code&gt; and &lt;code&gt;pyproject.toml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flg8o83qse3od877fpojq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flg8o83qse3od877fpojq.png" alt="poetry new poetry-test" width="367" height="39"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgq3ywirxhuaq10klg9b6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgq3ywirxhuaq10klg9b6.png" alt="output dir structure" width="366" height="140"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I, however, prefer using &lt;code&gt;poetry init&lt;/code&gt; to initialize poetry in a project. This allows me to manually configure the directory structure.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can find the code used in this article at my &lt;a href="https://github.com/kanakOS01/poetry-test" rel="noopener noreferrer"&gt;github repository&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;1) &lt;strong&gt;Create project directory&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;poetry-test &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;poetry-test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2) &lt;strong&gt;Initialize Poetry&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This will run an interactive module in which you can enter values according to your needs.&lt;br&gt;
After running it will only create a &lt;code&gt;pyproject.toml&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9x95udewyshbebeh7k4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9x95udewyshbebeh7k4.png" alt="poetry init" width="647" height="584"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3) &lt;strong&gt;Setup Directory Structure&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For this article we will make a simple fastapi endpoint so I will follow the general dir structure of a fastapi application along with a &lt;code&gt;README.md&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsuth2lbyz5f8ce8op548.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsuth2lbyz5f8ce8op548.png" alt="dir structure" width="491" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4) &lt;strong&gt;Installing dependencies&lt;/strong&gt;: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We only have one dependency as of now - "fastapi[standard]".&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry add &lt;span class="s2"&gt;"fastapi[standard]"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;You can mention a particular version as well. Running this will update the &lt;code&gt;pyproject.toml&lt;/code&gt; and create a &lt;code&gt;poetry.lock&lt;/code&gt; file.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;5) &lt;strong&gt;Fastapi endpoint code&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Add this code in the &lt;code&gt;app/main.py&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nd"&gt;@app.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;root&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello World&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now to run this server run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry run fastapi dev app/main.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then go to &lt;a href="http://localhost:8000/" rel="noopener noreferrer"&gt;http://localhost:8000/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And that's it. The server is up.&lt;/p&gt;



&lt;h2&gt;
  
  
  Poetry commands
&lt;/h2&gt;

&lt;p&gt;Now let's take a look at the poetry commands we used (and some more) to understand what exactly they do.&lt;/p&gt;

&lt;p&gt;1) &lt;strong&gt;poetry init&lt;/strong&gt; - Initialize a poetry project interactively.&lt;/p&gt;

&lt;p&gt;2) &lt;strong&gt;poetry add &lt;/strong&gt; - Add a dependency to the environment.&lt;/p&gt;

&lt;p&gt;3) &lt;strong&gt;poetry add --dev &lt;/strong&gt; - Add a dev dependency to the environment.&lt;/p&gt;

&lt;p&gt;4) &lt;strong&gt;poetry install&lt;/strong&gt; - If you have a &lt;code&gt;pyproject.toml&lt;/code&gt; file you can run this to install the dependencies.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Similar to &lt;code&gt;pip install -r requirements.txt&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;5) &lt;strong&gt;poetry run &lt;/strong&gt; - This allows us to run a command in the poetry environment without actually entering the environment.&lt;/p&gt;

&lt;p&gt;6) &lt;strong&gt;poetry shell&lt;/strong&gt; - This allows you to enter the poetry environment.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Similar to &lt;code&gt;sourcing&lt;/code&gt; the virtual environment.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In newer poetry versions the shell command does not come built-in but needs to be installed as a plugin. &lt;br&gt;
This can be done with the following command -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pipx inject poetry poetry-plugin-shell
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;7) &lt;strong&gt;poetry show&lt;/strong&gt; - Lists the installed dependencies.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Similar to &lt;code&gt;pip freeze&lt;/code&gt; or &lt;code&gt;pip list&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;8) &lt;strong&gt;poetry show --tree&lt;/strong&gt; - Lists the installed dependencies in tree form(recommended).&lt;/p&gt;




&lt;p&gt;And, that's it from my side. Check out the docs of poetry at &lt;a href="https://python-poetry.org/docs/" rel="noopener noreferrer"&gt;https://python-poetry.org/docs/&lt;/a&gt; for other info.&lt;br&gt;
Byee.&lt;/p&gt;

</description>
      <category>python</category>
      <category>poetry</category>
      <category>tooling</category>
      <category>programming</category>
    </item>
    <item>
      <title>Setup Zsh on Ubuntu (How and Why)</title>
      <dc:creator>Kanak Tanwar</dc:creator>
      <pubDate>Tue, 18 Feb 2025 15:03:51 +0000</pubDate>
      <link>https://dev.to/kanakos01/setup-zsh-on-ubuntu-how-and-why-2kl4</link>
      <guid>https://dev.to/kanakos01/setup-zsh-on-ubuntu-how-and-why-2kl4</guid>
      <description>&lt;p&gt;I have been using Zsh for a really long time. Why? I don't know just because. And, it is pretty cool. You can get a ton of customizations make your terminal look better and feel help yourself feel like a better developer (you r not).&lt;/p&gt;

&lt;p&gt;Well, anyways I sort of fked up my graphic drivers and has to reinstall Ubuntu and set up everything (including Zsh) so I thought I'd write article while I am at it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Psh, this setup is for Ubuntu only, incase u didn't read the title ;)&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h2&gt;
  
  
  What is Zsh?
&lt;/h2&gt;

&lt;p&gt;Zsh(short for &lt;code&gt;Z shell&lt;/code&gt;) is a shell...&lt;/p&gt;

&lt;p&gt;Ok so on a serious note, Zsh is a program that lets you interact with your computer using commands instead of clicking around with a mouse. So... it is a shell.&lt;br&gt;
That's it.&lt;/p&gt;

&lt;p&gt;The great thing about Zsh however is that it has a ton of options for customizations unlike &lt;code&gt;Bash&lt;/code&gt; which is the default shell in Ubuntu.&lt;/p&gt;



&lt;h2&gt;
  
  
  Why is Zsh better than Bash?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Rich customization&lt;/li&gt;
&lt;li&gt;Better plugins&lt;/li&gt;
&lt;li&gt;Stronger autosuggestions and tab completions&lt;/li&gt;
&lt;li&gt;Cooler&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl2qlxkcf5egax2jtkq68.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl2qlxkcf5egax2jtkq68.png" alt="Zsh" width="800" height="283"&gt;&lt;/a&gt;&lt;br&gt;
(isn't this so much better that out of the box bash?)&lt;/p&gt;



&lt;h2&gt;
  
  
  Setting up Zsh
&lt;/h2&gt;

&lt;p&gt;1) Make sure your system is up to date before starting.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
2) Install &lt;a href="https://www.zsh.org/" rel="noopener noreferrer"&gt;Zsh&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install zsh -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
3) Change default shell to Zsh&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chsh -s /usr/bin/zsh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;You may need to restart the terminal for this to take place.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
4) Install &lt;a href="https://github.com/ohmyzsh/ohmyzsh" rel="noopener noreferrer"&gt;Oh My Zsh&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Oh My Zsh allows you to easily manage your Zsh configuration.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9cv9r9jhhyxlqjpti3iw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9cv9r9jhhyxlqjpti3iw.png" alt="Oh My Zsh" width="800" height="254"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
5) Install &lt;a href="https://github.com/powerline/fonts" rel="noopener noreferrer"&gt;powerline fonts&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt-get install fonts-powerline
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Helps improve prompt visuals&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
6) Install &lt;a href="https://github.com/romkatv/powerlevel10k" rel="noopener noreferrer"&gt;powerlevel10k&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Powerlevel10k is a custom theme for Zsh. Like dark/light themes, but more powerful&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
7) Install dconf-cli&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt-get install dconf-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
8) Install Zsh Plugins&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/zsh-users/zsh-autosuggestions.git $ZSH_CUSTOM/plugins/zsh-autosuggestions
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git $ZSH_CUSTOM/plugins/zsh-syntax-highlighting
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Zsh has a lot of plugins. These 2 will give syntax highlighting and autosuggestion based on history.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
9) Update &lt;code&gt;~/.zshrc&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Now we need to update the &lt;code&gt;~/.zshrc&lt;/code&gt; file so that all the changes we have made can take effect.&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nano ~/.zshrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Find a line which says &lt;code&gt;ZSH_THEME="&amp;lt;theme_name&amp;gt;"&lt;/code&gt; and replace it with &lt;code&gt;ZSH_THEME="powerlevel10k/powerlevel10k"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Find a line which says &lt;code&gt;plugins=(git)&lt;/code&gt; and replace it with &lt;code&gt;plugins=(git zsh-autosuggestions zsh-syntax-highlighting)&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now exit the editor and apply the changes you made using&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source ~/.zshrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
10) Customize using powerlevel10k&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can now use the powerlevel10k (p10k) theme to customize your terminal. It will ask you some questions which you just have to answer and you will be done.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is possible that the configuration will run automatically after you &lt;code&gt;source&lt;/code&gt; the &lt;code&gt;.zshrc&lt;/code&gt; file. If it does not then you can run it with the following command. This can be repeated anytime in the future.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;p10k configure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;And you are done.&lt;/p&gt;

&lt;p&gt;If at any point some effects do not seem to take place close and reopen the terminal.&lt;/p&gt;

&lt;p&gt;Thanks. Bye.&lt;/p&gt;

</description>
      <category>ubuntu</category>
      <category>zsh</category>
      <category>terminal</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Create a CLI application with Python</title>
      <dc:creator>Kanak Tanwar</dc:creator>
      <pubDate>Sun, 09 Feb 2025 09:42:44 +0000</pubDate>
      <link>https://dev.to/kanakos01/create-a-cli-application-with-python-1j37</link>
      <guid>https://dev.to/kanakos01/create-a-cli-application-with-python-1j37</guid>
      <description>&lt;p&gt;A CLI(command line interface) application is a software tool that allows users to interact with an application directly through your terminal/command prompt.&lt;/p&gt;

&lt;p&gt;They are not just useful but also low-key cool ;)&lt;/p&gt;



&lt;h2&gt;
  
  
  CLI Intro
&lt;/h2&gt;

&lt;p&gt;A CLI application consists of various components - &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Commands&lt;/strong&gt; - The program that runs in the terminal window (like &lt;code&gt;git&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subcommands&lt;/strong&gt; - An optional identifier that comes after the command to do a certain task (like &lt;code&gt;commit&lt;/code&gt; in &lt;code&gt;git commit&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Arguments&lt;/strong&gt; - An optional/required piece of data used by a command/subcommand for processing (like &lt;code&gt;"initial commit"&lt;/code&gt; in &lt;code&gt;git commit -m "initial commit"&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Option/flag&lt;/strong&gt; - An option argument that modifies the commands behaviour (like &lt;code&gt;-m&lt;/code&gt; in &lt;code&gt;git commit -m&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;



&lt;h2&gt;
  
  
  Creating a CLI with &lt;code&gt;argparse&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Creating CLI applications may seem like a big deal but it is actually pretty simple. The difficult part in the project is usually the core logic and not the cli portion.&lt;/p&gt;

&lt;p&gt;Python has a built in module &lt;code&gt;argparse&lt;/code&gt; which allows us to interact with the cli with minimal code.&lt;/p&gt;

&lt;p&gt;Let's see how we can build a simple CLI calculator in python using argparse. It will have the capability to perform the 4 basic arithmetic operations and will be called from the CLI as such - &lt;code&gt;calcli add 5 10&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The code used in this post is available at &lt;a href="https://github.com/kanakOS01/calcli" rel="noopener noreferrer"&gt;this github repo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h3&gt;
  
  
  Directory Structure
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
├── calcli
│   ├── calculator.py
│   ├── __init__.py
│   └── __main__.py
├── README.md
├── requirements.txt
└── setup.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;calcli&lt;/code&gt; is the name of the package/cli tool.&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;calculator.py&lt;/code&gt; file has the logic for +,-,*,% operations.&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;__init__.py&lt;/code&gt; is used to define that &lt;code&gt;calcli&lt;/code&gt; is to be treated as a package. this file will be empty.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;__main__.py&lt;/code&gt; holds the logic to interact with the CLI. the main motive behind this post.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;setup.py&lt;/code&gt; is used to package the application&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  calculator.py
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mul&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;div&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Division by 0 NOT supported&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;main&lt;/strong&gt;.py
&lt;/h3&gt;

&lt;p&gt;1) &lt;u&gt;parser object&lt;/u&gt; - First we will create an object that will help us parse through the arguments given in CLI. This is done with using &lt;code&gt;argparse.ArgumentParser(description="...")&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;argparse&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;calcli.calculator&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Calculator&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;calculator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;argparse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ArgumentParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A CLI Calculator Tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;epilog&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Example calcli add 5 10&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2) &lt;u&gt;adding arguments&lt;/u&gt; - With argparse we can add arguments for commands and subcommands using the &lt;code&gt;add_argument()&lt;/code&gt; method.&lt;br&gt;
The first 2 parameters of this method are the long-hand and short-hand names of the argument/option, followed by optional parameters like &lt;code&gt;type&lt;/code&gt;, &lt;code&gt;default&lt;/code&gt;, &lt;code&gt;help&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;calculator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;argparse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ArgumentParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A CLI Calculator Tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;epilog&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Example calcli add 5 10&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--precision&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-p&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Number of decimal places&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3) &lt;u&gt;subparser&lt;/u&gt; - Subparsers are used to add subcommands (add, sub, div, mul in our case).&lt;br&gt;
The &lt;code&gt;title&lt;/code&gt; is a placeholder for the subparser and the &lt;code&gt;dest&lt;/code&gt; is the place where the arguments passed from the cli will be stored.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;calculator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;argparse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ArgumentParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A CLI Calculator Tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;epilog&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Example calcli add 5 10&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--precision&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-p&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Number of decimal places&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;subparsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_subparsers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Operators&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;operator&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4) &lt;u&gt;adding subcommands&lt;/u&gt; - We can now add the subcommands (add, sub, mul, div) using the subparser we created. This is done with the help of &lt;code&gt;add_parser()&lt;/code&gt; method followed by using the &lt;code&gt;add_argument()&lt;/code&gt; method to add arguments for the subcommands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;calculator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;argparse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ArgumentParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A CLI Calculator Tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;epilog&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Example calcli add 5 10&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--precision&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-p&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Number of decimal places&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;subparsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_subparsers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Operators&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;operator&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;add_parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subparsers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_parser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;add&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Add 2 numbers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;add_parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;First number&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;add_parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Second number&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;sub_parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subparsers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_parser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sub&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Subtract 2 numbers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sub_parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;First number&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sub_parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Second number&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;mul_parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subparsers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_parser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mul&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Multiply 2 numbers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;mul_parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;First number&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;mul_parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Second number&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;div_parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subparsers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_parser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;div&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Divide 2 numbers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;div_parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;First number&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;div_parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Second number&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;5) &lt;u&gt;access cli arguments&lt;/u&gt; - You can get the arguments passed in a command using the &lt;code&gt;parse_args()&lt;/code&gt; method.&lt;br&gt;
We can access the attributes of the args, which are the &lt;code&gt;dest=...&lt;/code&gt; parameter mentioned above, and perform actions with the arguments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse_args&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;operator&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;add&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;precision&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Result: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;operator&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sub&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;precision&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Result: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;operator&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mul&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mul&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;precision&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Result: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;operator&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;div&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;div&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;precision&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Result: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;ValueError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;print_help&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can now run the package with &lt;code&gt;python -m calcli &amp;lt;op&amp;gt; &amp;lt;a&amp;gt; &amp;lt;b&amp;gt;&lt;/code&gt;. This is because python treats calcli as a package.&lt;/p&gt;

&lt;p&gt;However we want to access this functionality directly as a utility. This is done by creating a &lt;code&gt;setup.py&lt;/code&gt; file which allows us to make the package installable.&lt;/p&gt;

&lt;h3&gt;
  
  
  setup.py
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;setup.py&lt;/code&gt; has a standard structure. You start by importing &lt;code&gt;setuptools.setup&lt;/code&gt; and use it to manage some metadate about the module we have just created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;setuptools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt;

&lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;calcli&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;6.9&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;calcli&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;entry_points&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;console_scripts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;calcli = calcli.__main__:main&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A CLI calculator using argparse&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Your Name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Project URL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;python_requires&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;=3.6&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's take a look at the parameters in &lt;code&gt;setup()&lt;/code&gt; -&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;name - name of the package&lt;/li&gt;
&lt;li&gt;version - current version&lt;/li&gt;
&lt;li&gt;entry_points - stores the commands that will be accessible through the CLI. here when we type &lt;code&gt;calcli&lt;/code&gt; the &lt;code&gt;calcli.__main__:main&lt;/code&gt; script will be executed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After you create a &lt;code&gt;setup.py&lt;/code&gt; you are ready to build the package.&lt;br&gt;
Now, there are 2 options - &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;pip install .&lt;/code&gt; - This builds the CLI tool. (Useful for testing)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pip install -e .&lt;/code&gt; - This builds the CLI tool in editable mode i.e. any changes you make will be reflected almost instantaneously. (Useful for development)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run the command that you would like and you are done.&lt;br&gt;
You CLI tool is ready.&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;calcli add 6 9&lt;/code&gt; or &lt;code&gt;calcli --help&lt;/code&gt; or &lt;code&gt;calcli div 6 9 -p 5&lt;/code&gt; and so on.&lt;/p&gt;




&lt;br&gt;&lt;br&gt;
That's all from my side. If you have any questions or suggestions do comment them.

</description>
      <category>python</category>
      <category>cli</category>
      <category>programming</category>
    </item>
    <item>
      <title>Using Daytona to maintain a Development Environment</title>
      <dc:creator>Kanak Tanwar</dc:creator>
      <pubDate>Thu, 09 Jan 2025 05:48:35 +0000</pubDate>
      <link>https://dev.to/kanakos01/using-daytona-to-maintain-a-development-environment-540b</link>
      <guid>https://dev.to/kanakos01/using-daytona-to-maintain-a-development-environment-540b</guid>
      <description>&lt;p&gt;As a developer and someone exploring Open Source, setting up new projects and configuring their development environments have been such a headache and a time eater.&lt;/p&gt;

&lt;p&gt;I found Daytona in the &lt;a href="https://quira.sh/quests/creator/details?questId=23" rel="noopener noreferrer"&gt;Quira Quest 23&lt;/a&gt;. Our task was to  use Daytona to configure and automate our development environment.&lt;/p&gt;

&lt;p&gt;Sounds difficult? Not so much. Just 3 steps and I was all done.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Setup your project in you system
&lt;/h3&gt;

&lt;p&gt;In my case this was already done. I had a RAG application that allows you to have a q/a session with any github repository of your choice.&lt;br&gt;
It uses Daytona for managing environment, weaviate cloud vector database to store the embeddings, LangChain with OpenAI for llm models and facilitate queries with context and streamlit for UI.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Create a &lt;code&gt;.devcontainer/devcontainer.json&lt;/code&gt; file in the root dir of the project.
&lt;/h3&gt;
&lt;h3&gt;
  
  
  3. Generate a &lt;code&gt;devcontainer.json&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Go to &lt;a href="https://devcontainer.ai/" rel="noopener noreferrer"&gt;DevContainer.ai&lt;/a&gt;, create your own devcontainer.json using AI and paste its content in the file you created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "name": "Git Chat Development Environment",
  "image": "mcr.microsoft.com/devcontainers/base:ubuntu", 
  "features": {
    "python": "3.10"
  },
  "forwardPorts": [
    8501
  ],
  "customizations": {
    "vscode": {
      "settings": {
        "python.defaultInterpreterPath": "${workspaceFolder}/gitchat-venv/bin/python",
        "python.linting.enabled": true,
        "python.linting.pylintEnabled": true,
        "python.formatting.autopep8Path": "${workspaceFolder}/gitchat-venv/bin/autopep8",
        "python.formatting.blackPath": "${workspaceFolder}/gitchat-venv/bin/black",
        "python.linting.flake8Path": "${workspaceFolder}/gitchat-venv/bin/flake8",
        "python.linting.mypyPath": "${workspaceFolder}/gitchat-venv/bin/mypy",
        "python.linting.pydocstylePath": "${workspaceFolder}/gitchat-venv/bin/pydocstyle",
        "python.linting.pycodestylePath": "${workspaceFolder}/gitchat-venv/bin/pycodestyle"
      },
      "extensions": [
        "ms-python.python",
        "ms-python.vscode-pylance",
        "njpwerner.autodocstring"
      ]
    }
  },
  "postCreateCommand": "python -m venv gitchat-venv &amp;amp;&amp;amp; . gitchat-venv/bin/activate &amp;amp;&amp;amp; pip install -r requirements.txt"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And you are done. That's it.&lt;br&gt;
But what are the benefits of this you ask?&lt;br&gt;
Here you go.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3fyda2k868ks5iy0zl3g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3fyda2k868ks5iy0zl3g.png" alt="Benefits of Dev Containers" width="800" height="181"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  How Daytona comes into play
&lt;/h2&gt;

&lt;p&gt;Daytona abstracts a lot of steps and allows you to setup development containers without much effort.  It simplifies the process of managing environments by providing a clean, modular workspace. Instead of manually cloning repositories, setting up environments, and troubleshooting dependencies, Daytona handles it with a few commands.&lt;/p&gt;
&lt;h2&gt;
  
  
  Getting started with Daytona
&lt;/h2&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://www.daytona.io/docs/" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.daytona.io%2Fdocs%2Fdaytona.png" height="402" class="m-0" width="800"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://www.daytona.io/docs/" rel="noopener noreferrer" class="c-link"&gt;
          Documentation · Daytona
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          Start managing your Workspaces with Daytona.
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.daytona.io%2Fdocs%2Ffavicon.ico" width="800" height="400"&gt;
        daytona.io
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://www.daytona.io/docs/" rel="noopener noreferrer"&gt;daytona documentation&lt;/a&gt; is very easy to go through. Here I will be going through some basic steps to setup and use Daytona. You can browse the docs for detailed info.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Installing Daytona
&lt;/h3&gt;

&lt;p&gt;For Linux, run this in your shell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(curl -sf -L https://download.daytona.io/daytona/install.sh | sudo bash) &amp;amp;&amp;amp; daytona server -y &amp;amp;&amp;amp; daytona
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Checkout the &lt;a href="https://www.daytona.io/docs/installation/installation/" rel="noopener noreferrer"&gt;installation guide&lt;/a&gt; for other OS.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2. Configurations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;git providers&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;daytona git-providers add
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This helps you work with git and manage your repositories. There are a number of options like &lt;em&gt;github&lt;/em&gt;, &lt;em&gt;gitlab&lt;/em&gt;, &lt;em&gt;bitbucket&lt;/em&gt; etc. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;providers&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;daytona provider install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows you to connect to a provider like &lt;em&gt;GCP&lt;/em&gt;, &lt;em&gt;AWS&lt;/em&gt; etc.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;set target&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;daytona target set
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;target&lt;/code&gt; is the location where you want to set up your development environment. &lt;br&gt;
Select &lt;code&gt;docker&lt;/code&gt; if you want to set it up locally on you system.&lt;br&gt;
Select the configurations as they popup. I used all the default configs with docker server.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;select ide&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;daytona ide
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Daytona allows you to work with you preferred IDE out of the box without you configuring various things. You can also include IDE specific settings in you &lt;code&gt;.devcontainer/devcontainer.json&lt;/code&gt; file to customize the dev env further.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Create Workspace
&lt;/h3&gt;

&lt;p&gt;A workspace is a dedicated development environment for the project you are working on.&lt;/p&gt;

&lt;p&gt;This can be done simply with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;daytona create https://github.com/kanakOS01/gitchat-daytona
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is my project url which has a &lt;code&gt;.devcontainer/devcontainer.json&lt;/code&gt; file. You can replace this with any repo which has a devcontainer.json file in it.&lt;/p&gt;

&lt;p&gt;You can find a list of sample repos which you can try out &lt;a href="https://github.com/daytonaio/daytona/blob/main/hack/samples/index.json" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Takeaways from Using Daytona
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Time Saved&lt;/strong&gt;: By automating repetitive setup tasks, Daytona allowed me to focus on building Git Chat’s core functionality.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistency Across Environments&lt;/strong&gt;: Whether I worked locally or collaborated with others, Daytona ensured the environment was identical every time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ease of Use&lt;/strong&gt;: The intuitive CLI commands and clear documentation made Daytona accessible even for someone trying it for the first time.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>opensource</category>
      <category>daytona</category>
      <category>development</category>
    </item>
  </channel>
</rss>
