<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/atom.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:fh="http://purl.org/syndication/history/1.0">
  <title>Thoughts on tech Archive</title>
  <id>https://pype.dev/tech/archive/atom.xml</id>
  <updated>2026-10-06T21:30:00Z</updated>
  <subtitle>My thoughts and streams of consciousness organized into barely coherent posts about things</subtitle>
  <link href="https://pype.dev/tech/" rel="alternate" type="text/html"></link>
  <link href="https://pype.dev/tech/archive/atom.xml" rel="self" type="application/atom+xml"></link>
  <link href="https://pype.dev/tech/atom.xml" rel="current" type="application/atom+xml"></link>
  <author>
    <name>Nic Payne</name>
  </author>
  <generator uri="https://github.com/WaylonWalker/markata-go">markata-go</generator>
  <fh:complete></fh:complete>
  <entry>
    <title>The Faulted Disk: harbor Replacement Writeup</title>
    <id>https://pype.dev/harbor-faulted-disk-replacement/</id>
    <updated>2026-10-06T21:30:00Z</updated>
    <published>2026-10-06T21:30:00Z</published>
    <link href="https://pype.dev/harbor-faulted-disk-replacement/" rel="alternate" type="text/html"></link>
    <summary type="text">The sequel to panicking-led-to-losing-my-desktop — this time the monitoring actually caught the disk dying, and nothing was lost.</summary>
    <content type="html">&lt;p&gt;The sequel to &lt;a href=&#34;/panicking-led-to-losing-my-desktop&#34;&gt;panicking-led-to-losing-my-desktop&lt;/a&gt; — this time the monitoring actually caught the disk dying, and nothing was lost.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-happened&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;What happened&lt;/span&gt; &lt;a href=&#34;#what-happened&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;&lt;code&gt;harbor&lt;/code&gt; is my replica pool — a 10.9T mirror (2x 12TB) that receives syncoid snapshots from &lt;code&gt;tank&lt;/code&gt;. One side of the mirror, a Seagate Exos &lt;code&gt;ST12000NM0127&lt;/code&gt; (serial &lt;code&gt;ZJV4QFLB&lt;/code&gt;, &lt;code&gt;/dev/sdb&lt;/code&gt;), went &lt;strong&gt;FAULTED&lt;/strong&gt; with 14 read + 22 checksum errors.&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;mirror-0                              DEGRADED     0     0     0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  ata-ST12000VN0008-2PH103_ZTM0NFDW  ONLINE       0     0     0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  ata-ST12000NM0127_ZJV4QFLB         FAULTED     14     0    22  too many errors&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The IronWolf mirror side carried the pool — &lt;code&gt;No known data errors&lt;/code&gt;. ZFS redundancy did exactly its job.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-difference-from-last-time&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The difference from last time&lt;/span&gt; &lt;a href=&#34;#the-difference-from-last-time&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Last failure: no monitoring, found out by accident months later, desktop died.&lt;/p&gt;&#xA;&lt;p&gt;This failure: SigNoz + node-exporter&amp;rsquo;s ZFS collector → &lt;code&gt;node_zfs_zpool_state{state=&amp;quot;degraded&amp;quot;}&lt;/code&gt; → alert rule → Gotify → my phone. The gotify notification fired &lt;em&gt;before&lt;/em&gt; I knew anything was wrong.&lt;/p&gt;&#xA;&lt;h2 id=&#34;diagnosis&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Diagnosis&lt;/span&gt; &lt;a href=&#34;#diagnosis&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Before &lt;code&gt;zpool clear&lt;/code&gt; or replace — check SMART. &lt;code&gt;smartctl-exporter&lt;/code&gt; already scrapes all disks into SigNoz, so I didn&amp;rsquo;t even need sudo:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;Reallocated_Sector_Ct&lt;/code&gt; raw = &lt;strong&gt;3024&lt;/strong&gt; and counting&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Offline_Uncorrectable&lt;/code&gt; value/worst still 100 but raw errors climbing&lt;/li&gt;&#xA;&lt;li&gt;SMART overall: still PASS (SMART&amp;rsquo;s overall bit is conservative until threshold)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;3k+ remapped sectors is a platter going bad — not a cable blip. Verdict: replace, don&amp;rsquo;t clear.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-swap-the-annoying-part&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The swap (the annoying part)&lt;/span&gt; &lt;a href=&#34;#the-swap-the-annoying-part&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Hot-plug is never as smooth as it should be:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;code&gt;zpool offline harbor &amp;lt;old&amp;gt;&lt;/code&gt; to stop writes to the dead drive — actually skipped; drive fell off the bus on its own&lt;/li&gt;&#xA;&lt;li&gt;New IronWolf &lt;code&gt;ZTN1CQ07&lt;/code&gt; in hand → plugged into ghost&amp;rsquo;s SATA → &lt;strong&gt;didn&amp;rsquo;t enumerate&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;Forced rescan (&lt;code&gt;echo &amp;quot;- - -&amp;quot; | sudo tee /sys/class/scsi_host/host*/scan&lt;/code&gt;) → nothing&lt;/li&gt;&#xA;&lt;li&gt;Moved it to the &lt;em&gt;old drive&amp;rsquo;s port&lt;/em&gt; → nothing&lt;/li&gt;&#xA;&lt;li&gt;Sabrent USB dock on aurora → dock enumerated as &lt;code&gt;0B&lt;/code&gt; device, no disk behind it → reseated + replugged → &lt;strong&gt;drive spun up and appeared&lt;/strong&gt;: &lt;code&gt;/dev/sdd&lt;/code&gt;, 10.9T, old ZFS partition table on it (used drive — &lt;code&gt;part1&lt;/code&gt;/&lt;code&gt;part9&lt;/code&gt; layout)&lt;/li&gt;&#xA;&lt;li&gt;Back to ghost, direct SATA → enumerated as &lt;code&gt;sdb&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Lesson: &amp;ldquo;spins up but doesn&amp;rsquo;t enumerate&amp;rdquo; on direct SATA + dock-shows-0B = seating/power problem, not DOA. The drive was fine all along.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-replace&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The replace&lt;/span&gt; &lt;a href=&#34;#the-replace&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo zpool replace harbor &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  ata-ST12000NM0127_ZJV4QFLB &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  ata-ST12000VN0008-2PH103_ZTN1CQ07&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Resilver: &lt;strong&gt;8.80T in 18h38m, 0 errors&lt;/strong&gt; (~154M/s). Pool stayed online and usable the whole time.&lt;/p&gt;&#xA;&lt;p&gt;One gotcha: after resilver, &lt;code&gt;zpool status&lt;/code&gt; showed &lt;code&gt;errors: 1 data errors&lt;/code&gt; — but &lt;code&gt;zpool status -v&lt;/code&gt; showed an &lt;strong&gt;empty error list&lt;/strong&gt;. The corrupted data was already repaired; the counter was just stale. &lt;code&gt;sudo zpool clear harbor&lt;/code&gt; → clean.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-monitoring-that-made-this-possible&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The monitoring that made this possible&lt;/span&gt; &lt;a href=&#34;#the-monitoring-that-made-this-possible&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Wired during this session (all now in SigNoz):&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;node_zfs_zpool_state&lt;/code&gt; — pool health (node-exporter zfs collector)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;smartctl-exporter&lt;/code&gt; — SMART attributes incl. reallocated sectors (the early-death signal)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;zfs-metrics.sh&lt;/code&gt; textfile bridge — sanoid &lt;code&gt;--monitor-*&lt;/code&gt; exit codes, zpool error counters, scrub ages, resilver %, syncoid last-success&lt;/li&gt;&#xA;&lt;li&gt;Alert rules → Gotify → phone&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;The replication alerting even proved itself live: syncoid failed twice during the resilver window and I got paged on both. Turned out to be send-time contention — self-healed once resilver finished — but the notification path works end to end.&lt;/p&gt;&#xA;&lt;h2 id=&#34;remaining-homework&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Remaining homework&lt;/span&gt; &lt;a href=&#34;#remaining-homework&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Buy the replacement spare (the shelf&amp;rsquo;s empty now)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;10Fold&lt;/code&gt; datasets are garbage + have zero snapshots — destroy&lt;/li&gt;&#xA;&lt;li&gt;Every scheduled job emits &lt;code&gt;cron_last_success_epoch&lt;/code&gt; now — if a job dies silently again, I&amp;rsquo;ll know&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Same failure as April, opposite outcome. Redundancy did the protection; monitoring did the &lt;em&gt;detection&lt;/em&gt;. You need both.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;p&gt;&lt;em&gt;Co-authored with Devin, who ran the monitoring stack, the SMART diagnosis, and the alerting loop.&lt;/em&gt;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>It Will Be Hard To Do More</title>
    <id>https://pype.dev/it-will-be-hard-to-do-more/</id>
    <updated>2026-05-22T06:23:20Z</updated>
    <published>2026-05-22T06:23:20Z</published>
    <link href="https://pype.dev/it-will-be-hard-to-do-more/" rel="alternate" type="text/html"></link>
    <summary type="text">Recently I was given a raise at work after I broached the subject with my manager. I wasn&#39;t sure what the outcome would be but I have learned two things in...</summary>
    <content type="html">&lt;p&gt;Recently I was given a raise at work after I broached the subject with my&#xA;manager. I wasn&amp;rsquo;t sure what the outcome would be but I have learned two things&#xA;in nearly a decade in corporate America:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;No one will fight for you harder than yourself&lt;/li&gt;&#xA;&lt;li&gt;The worst they can say is no&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;the-raise&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Raise&lt;/span&gt; &lt;a href=&#34;#the-raise&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;So I talked with my manager about my workload and compensation, and to my&#xA;surprise he took me seriously. He went up the chain with some accomplishments&#xA;of the year that I wrote up for him (it&amp;rsquo;s his job to advocate for me, but it&amp;rsquo;s&#xA;certainly my job to give him the ammunition to take into battle). Before much&#xA;time had passed, a big wig put some time on my calendar. I had a good&#xA;relationship with my (then) manager, and even with the big wig, so there was&#xA;always some amount of personal connection amidst the money-talk.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-reorg&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Reorg&lt;/span&gt; &lt;a href=&#34;#the-reorg&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Cue a managerial change and reorganization of the team. The dust settled, and&#xA;my manager wasn&amp;rsquo;t my manager and the big wig wasn&amp;rsquo;t a big wig over my team&#xA;anymore. The details aren&amp;rsquo;t that relevant, but the outcome was that my &lt;em&gt;now&lt;/em&gt;&#xA;manager is someone I don&amp;rsquo;t know personally — back to square one of&#xA;professional-relationship-building.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-conversation&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Conversation&lt;/span&gt; &lt;a href=&#34;#the-conversation&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Due to the timing of it all, when my raise became official it was this new&#xA;manager who signed off on it. It was their happy-responsibility to have a quick&#xA;chat to tell me it was official. But that conversation was the most&#xA;awkward of the three.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Does this raise of X% close the gap with the other competing opportunities&#xA;you mentioned to (previous manager)? Because it&amp;rsquo;ll be hard to do more than&#xA;this.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;div class=&#34;admonition danger&#34;&gt;&#xA;&lt;p class=&#34;admonition-title&#34;&gt;???&lt;/p&gt;&#xA;&lt;p&gt;Hard to do more?&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;I was taken aback initially. It felt almost threatening.&lt;/p&gt;&#xA;&lt;p&gt;I really wasn&amp;rsquo;t sure how to respond. I think I was grateful and cordial,&#xA;talked about how I really do believe in the mission of our work and I&amp;rsquo;m&#xA;thankful that I can receive a raise. This lady is nice but she doesn&amp;rsquo;t know&#xA;what my &amp;ldquo;other opportunities&amp;rdquo; are, so there&amp;rsquo;s no honest answer for me to give.&#xA;I wanted to be sarcastic, crack a joke about record profits, make light of her&#xA;describing me as a &amp;ldquo;critical player in enterprise deliverables,&amp;rdquo; but I&amp;rsquo;m not&#xA;trying to make enemies.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-reframe&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Reframe&lt;/span&gt; &lt;a href=&#34;#the-reframe&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;So I called a friend to vent, of course, and he gave me some good advice.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;It was a threat.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;But not in the way I took it at first. My friend has been at the same company&#xA;longer than me, and he expounded on her words: &amp;ldquo;it will be hard to do more.&amp;rdquo;&#xA;I felt like she was annoyed with me for fighting for a raise, but my friend&#xA;said she was probably just trying to give me a realistic view of my position&#xA;in the company. &amp;ldquo;It will be hard to do more&amp;rdquo; means there are processes in&#xA;place at such a large enterprise. Rewarding start-up-like behavior and&#xA;contribution just isn&amp;rsquo;t well-supported. It&amp;rsquo;s much easier to let someone quit&#xA;who&amp;rsquo;s been with the company a decade and replace them for 20% more than it is&#xA;to just pay them 20% more. If someone (like me) isn&amp;rsquo;t satisfied, that&amp;rsquo;s not the&#xA;only thing in the conversation - time at the company, time in position, time&#xA;under specific manager, etc. all are hurdles to more compensation, and I&amp;rsquo;m&#xA;referring to salary anyways, equity feels like it&amp;rsquo;s out of my grasp. But if I&amp;rsquo;m&#xA;gone and market conditions dictate that my position and responsibilities are&#xA;worth 20% more than what I was being paid, that&amp;rsquo;s what the position will be&#xA;posted at. My previous manager and the big wig were the types to say&#xA;policy-be-damned when it would get in the way - it might be how I got this&#xA;raise in the first place. But no shade to my new manager, they&amp;rsquo;re just doing their job.&lt;/p&gt;&#xA;&lt;p&gt;In the end, they were just being honest, and I should appreciate that.&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Panicking Led to Losing My Desktop</title>
    <id>https://pype.dev/panicking-led-to-losing-my-desktop/</id>
    <updated>2026-05-13T08:24:00Z</updated>
    <published>2026-05-13T08:24:00Z</published>
    <link href="https://pype.dev/panicking-led-to-losing-my-desktop/" rel="alternate" type="text/html"></link>
    <summary type="text">I thought I had backups handled... can you imagine how the rest of this post is going to go with that intro?</summary>
    <content type="text">&#xA;## False Sense of Security&#xA;&#xA;I thought I had backups handled... can you imagine how the rest of this post is&#xA;going to go with that intro?&#xA;&#xA;To be fair, I do have backups figured out on my NAS - simple ZFS +&#xA;sanoid/syncoid + replica pool + off-site backup with simple restore pathways.&#xA;However, my desktop has been another story entirely. My desktop OS didn&#39;t&#xA;support ZFS when I started checking it out, and I spent weeks thinking through&#xA;how I would backup my HOME directory and projects mostly. I landed on a&#xA;solution that I did validate once, but it fell off my radar and lo&#39; and behold&#xA;that was problematic...&#xA;&#xA;So that backup was based on restic for my home directory, but it was lazy. I&#xA;verified it one time but I had built it with ai, thought I understood the&#xA;restic repo part, and then promptly moved on with my life never buttoning it&#xA;all up. That home directory backup got too big for where I was going to end up&#xA;restoring it. My desktop system was installed on a 4 TB NVMe drive and due to&#xA;the circumstances spawning this blog post I was gonna have to drop to a 500 GB&#xA;boot drive with some extra disks as the storage layer. Overall it looked like:&#xA;&#xA;- A 4 TB SSD that was going bad - old OS&#xA;- A 500 GB SSD, that was going to be my new operating system boot disk&#xA;- A 2 TB SSD that was originally going to be this external storage volume&#xA;  anyways but I never set it up because the version of Aurora I was running&#xA;  didn&#39;t have ZFS, I was married to the idea of using ZFS, so I never ended up&#xA;  taking advantage of the space. However it was moot to me because my boot drive&#xA;  was 4 TB, high quality drive, so I was &#34;just sure&#34; I didn&#39;t need it.&#xA;- AND a 4 TB rust disk as well, which was already a ZFS pool, left over from a&#xA;  previous desktop configuration, and admittedly I had forgotten it was even in the system.&#xA;&#xA;## The Storm&#xA;&#xA;If it wasn&#39;t clear the problem is that my super-nice high-speed 4TB NVMe drive&#xA;was going bad, like really bad. Eventually my OS stopped booting, it was even&#xA;difficult to live-boot from any other ISO due to, I think ultimately, that disk&#xA;causing such extreme latency in the start-up processes that they just failed.&#xA;So I quickly found myself with little-to-no access to my primary desktop&#39;s&#xA;data...&#xA;&#xA;## Where It Went Wrong&#xA;&#xA;What I did is I live booted into an Ubuntu server environment (which took blood&#xA;sweat and tears to successfully get into), mounted my home directory from the 4 TB SSD, and&#xA;tried to continue my restic backup to my NAS, like an idiot. But at the same&#xA;time I also tried to prune it by only backing up a few projects because I&#xA;was getting worried about time. This was the first primary mistake - trying to&#xA;muck with my backup script under duress.&#xA;&#xA;Then over the course of the whole thing it ended up taking over a week to solve&#xA;this when it could&#39;ve been 2-3 days. So say it with me kids - &#34;Don&#39;t make&#xA;decisions under duress&#34;&#xA;&#xA;## Climbing Out&#xA;&#xA;I downloaded opencode and had it help me write the right excludes syntax in my&#xA;restic backup script and got it back up going. That went ok but opencode agents&#xA;had no historical context for why anything was the way it was, and frankly an&#xA;agent would&#39;ve been misled thinking the backup solution was much more solid&#xA;than it was due to how I documented it.&#xA;&#xA;Agents also miss things... in my chat sessions it knew about the other 2&#xA;available disks on the desktop system, I could have done a fresh backup to the 4 TB&#xA;spinning rust disk no problem: install zfs, mount the pool, change target of&#xA;restic, run full... that would&#39;ve been beautifully simple. But instead I&#xA;trimmed it down and backed not-everything up to the NAS over the network, and&#xA;to a different backup target nonetheless... SMH.&#xA;&#xA;As I started to consider which OS I was going to go with next I failed to&#xA;install Pop_OS! or Ubuntu onto the new disc... Then I tried Omarchy and the&#xA;install script just looped. So, I reinstalled Aurora onto the new 500 GB disk&#xA;and then quickly realized I don&#39;t have Firefox tabs, my SSH keys are in that&#xA;restic backup, my ssh config, api keys in hidden files.... Everything is in&#xA;that restic backup... The backup that&#39;s too big to restore to my new boot drive.&#xA;&#xA;But you know what I have? That 2 terabyte disk mounted just fine as a&#xA;ZFS dataset. And I could mount the 4 TB rust disk with zfs as well because this&#xA;version of Aurora has zfs working flawlessly!&#xA;&#xA;## Hindsight&#xA;&#xA;What I should&#39;ve done is so simple... While in that ubuntu live environment I&#xA;should&#39;ve just either updated restic to be a local backup to the 4 TB rust&#xA;disk, or rsync&#39;d my home directory to it plain and simple... I got all in my&#xA;head about not backing up python venvs, node_modules, etc. that I didn&#39;t think&#xA;to just basically carbon copy it all to a healthy disk and then prune it later.&#xA;Then I could&#39;ve synced everything back over that I needed to the new Desktop&#39;s&#xA;$HOME and then scheduled the rsync or restic again to that locally mounted disk.&#xA;&#xA;## The Detail I Left Out&#xA;&#xA;The keen reader might stop to think... why not just mount the old 4TB disk and&#xA;copy what you need to your new desktop? And that&#39;s a prudent question...&#xA;However, in order to get anything installed I had to physically remove the 4TB&#xA;SSD from the motherboard, which was basically a full PC tear-down. From there I&#xA;was able to at least boot in and out of iso&#39;s like you&#39;d otherwise expect, and&#xA;I have a USB/NVMe adapter so I planned to mount the old drive and copy things over from&#xA;there... But sadly... it won&#39;t mount. it&#39;s dead-dead and it appears that&#xA;anything I didn&#39;t save in my days-long-panicked-state is just. gone.&#xA;&#xA;I feel pretty stupid to have not taken advantage of the 2 available disks local&#xA;to the machine, to have naively copied stuff over and dealt with the&#xA;organization later once my OS was back up. I tried to be smart and efficient&#xA;and ended up wasting so much time and losing quite a lot of &#34;stuff&#34;... ideas,&#xA;blog posts that I never committed, etc.&#xA;&#xA;## Current Status&#xA;&#xA;So a few lessons...&#xA;&#xA;1. untested backups are not backups&#xA;2. false backups might be worse than none, although I did at least save a few things so maybe the jury is out here&#xA;3. making decisions while stressed out will lead to missing obviously better pathways... slow down, talk it out&#xA;&#xA;As for my current status - I&#39;m working on [[desktop-setup-2026]] and recovering what I can from my haphazard&#39;d rsyncs in the live ubuntu env I got into. I&#39;m also setting up a new Linux laptop at work at the same time so maybe I&#39;ll hve some workflow changes to write about in the future. For now, it&#39;s nice to be forced to accept that not every idea was that important, the good stuff will come back around, and ultimately computers and shit are just things, they&#39;re not life.&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>The Relief of Earning</title>
    <id>https://pype.dev/the-relief-of-earning/</id>
    <updated>2026-05-08T05:43:39Z</updated>
    <published>2026-05-08T05:43:39Z</published>
    <link href="https://pype.dev/the-relief-of-earning/" rel="alternate" type="text/html"></link>
    <summary type="text">Work has been crazy for months, and I haven&#39;t written too much about it, a few notes here and there but nothing substantial. The craziness is sourced in a...</summary>
    <content type="html">&lt;h2 id=&#34;the-setup&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Setup&lt;/span&gt; &lt;a href=&#34;#the-setup&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Work has been crazy for months, and I haven&amp;rsquo;t written too much about it, a few&#xA;notes here and there but nothing substantial. The craziness is sourced in a&#xA;pretty cliched-scenario where we have lofty goals and important things to build&#xA;but the foundation on which we are building, like architectural decisions, is&#xA;basically wet sand. So as I&amp;rsquo;ve been trying to find my footing in the mud I feel&#xA;like I end up spinning my wheels moreso than making any progress. The chaos led&#xA;me eventually to approach my manager about my compensation - I make a nice&#xA;living but for the stress I&amp;rsquo;d been feeling I could certainly go make more. My&#xA;manager successfully fought for me up the chain and I was given a slightly bigger&#xA;carrot, but that&amp;rsquo;s not the point of this post. I started to feel even more&#xA;anxiety after I was told about the raise because, just like with AI and agentic&#xA;coding, now I was sure the expectations would be even higher. I didn&amp;rsquo;t think&#xA;anything would actually come from me asking my boss about a raise, but now that&#xA;it did I was afraid the ceiling of expectations was just going up up up.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-carrot-and-the-anxiety&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Carrot and the Anxiety&lt;/span&gt; &lt;a href=&#34;#the-carrot-and-the-anxiety&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;That&amp;rsquo;s where the relief of earning comes in&amp;hellip; I mentioned this to my project&#xA;manager, and we have candid conversations regularly, and he told me something&#xA;that I think some people might have been offended by but I was genuinely&#xA;relieved to hear it. He said he&amp;rsquo;s glad I got a raise, and that he told our boss&#xA;to &lt;em&gt;not&lt;/em&gt; really pursue it for me until I had actually delivered something. So even&#xA;though I feel like I&amp;rsquo;m spinning my wheels a lot, my direct leadership sees real&#xA;value - and the relief is that I can rest in confirmation that the carrot is a&#xA;response to work I already did, not a quiet elevation of expectations.&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Fixing Firefox Launcher on Kubuntu 22</title>
    <id>https://pype.dev/fixing-firefox-launcher-on-kubuntu-22/</id>
    <updated>2026-04-11T10:32:50Z</updated>
    <published>2026-04-11T10:32:50Z</published>
    <link href="https://pype.dev/fixing-firefox-launcher-on-kubuntu-22/" rel="alternate" type="text/html"></link>
    <summary type="text">Problem: Firefox installed but missing from KDE/Plasma app menu - Root cause: No .desktop launcher file — Firefox only worked from terminal - Solution:...</summary>
    <content type="html">&lt;ul&gt;&#xA;&lt;li&gt;Problem: Firefox installed but missing from KDE/Plasma app menu&lt;/li&gt;&#xA;&lt;li&gt;Root cause: No .desktop launcher file — Firefox only worked from terminal&lt;/li&gt;&#xA;&lt;li&gt;Solution: Created desktop entry with standard KDE fields&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code&gt;&#xA;[Desktop Entry]&#xA;Version=1.0&#xA;Name=Firefox&#xA;GenericName=Web Browser&#xA;Comment=Web Browser&#xA;Exec=firefox %u&#xA;Terminal=false&#xA;Icon=firefox&#xA;Type=Application&#xA;Categories=Network;WebBrowser;&#xA;MimeType=x-scheme-handler/http;x-scheme-handler/https;&#xA;StartupNotify=true&#xA;StartupWMClass=firefox&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Location: ~/.local/share/applications/firefox.desktop (user-local, no sudo needed)&lt;/li&gt;&#xA;&lt;li&gt;Discovery step: Checked /usr/share/applications/ — empty for Firefox&lt;/li&gt;&#xA;&lt;li&gt;Applied fix: Ran kbuildsycoca5 to rebuild Plasma&amp;rsquo;s menu cache&lt;/li&gt;&#xA;&lt;li&gt;Result: Firefox now appears in app menu (Network category) and Alt+F2 autocomplete&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Data Loading is a Huge Deal</title>
    <id>https://pype.dev/data-loading-is-a-huge-deal/</id>
    <updated>2026-04-08T07:40:14Z</updated>
    <published>2026-04-08T07:40:14Z</published>
    <link href="https://pype.dev/data-loading-is-a-huge-deal/" rel="alternate" type="text/html"></link>
    <summary type="text">I&#39;ve been thinking about the work I am doing and have to do in my role at Cat, in Cat Autonomy, building Forge (see forge-ahead). I feel like I have little...</summary>
    <content type="text">&#xA;I&#39;ve been thinking about the work I am doing and have to do in my role at Cat,&#xA;in Cat Autonomy, building Forge (see [[forge-ahead]]). I feel like I have&#xA;little revelations almost every day now, not that it means I&#39;m writing&#xA;something amazing and producing it really fast but there&#39;s just a whole suite&#xA;of problems that different technologies solve at different levels and the more&#xA;I become aware of the problems that exist, the more the existence of some&#xA;solutions makes sense.&#xA;&#xA;!!! note &#34;The Problem Perspective&#34;&#xA;&#xA;    I don&#39;t know if this is a real thinking technique or if I&#39;m onto something&#xA;    novel(doubt) but I think a lot in terms of problems - &#34;what problem needs&#xA;    solving?&#34; and that&#39;s how I&#39;ve come to prioritize my work, it&#39;s only been very&#xA;    recently that I&#39;ve realized I do this and I think I should highlight it&#39;s very&#xA;    important to document the problem, otherwise every day you might try to solve a&#xA;    different problem but be working on the same code&#xA;&#xA;!!! note &#34;Problem Space&#34;&#xA;&#xA;    Kedro solves a lot of these problems, so when making rada in Reman the problem&#xA;    space was already more contained and narrow, Forge&#39;s problem-space is much more&#xA;    vast&#xA;&#xA;The one problem I&#39;m really fixated on right now is data loading, the problem I&#xA;need to solve is accessing data from a wide-variety of scripts/tools, without a&#xA;framework or standard method/library of accessing data in the first place. I&#39;ve&#xA;seen lots of projects on GitHub claim to make data loading easier and I didn&#39;t&#xA;quite understand what problem they were solving... one example to name is [Data&#xA;Load Tool](https://dlthub.com/). I&#39;ve seen similar ones I don&#39;t have the name&#xA;for right now that claim to make it easy/fast to load data from s3, or ways to&#xA;make s3 and a database both abstract in the user-experience for loading data.&#xA;But I hadn&#39;t really understood why these tools existed. I have a lot of&#xA;experience with [Kedro](https://dlthub.com/) and their&#xA;[DataCatalog](https://docs.kedro.org/en/latest/catalog-data/introduction/)&#xA;which provides a python object over a set of yamlfiles that makes it pretty&#xA;simple to load and save data in a way that isolates I/O from the business&#xA;logic. But what I didn&#39;t realize at the time how powerful that catalog was, the&#xA;power of standard patterns and shared libraries. Now that I don&#39;t have it&#xA;available to me, I&#39;m quite aware of the absence.&#xA;&#xA;In my new role something I&#39;m realizing is that for all the developers my team&#xA;now supports, there isn&#39;t a canonical way to access data. When I was in Reman&#xA;and working with kedro, the DataCatalog was the access pattern and so when I&#xA;was developing a platform I never really had to think about it - it was an&#xA;established pattern that I treated as a constraint and then built processes&#xA;around it. I&#39;ve been battling some mental block for weeks on Forge because of&#xA;the lack of that canonical pattern, and as I&#39;ve talked with other engineers it&#xA;seems like the baseline assumption is that data is just available on a&#xA;filesystem, but everyone&#39;s code loads data in different ways. On my small Reman&#xA;team, with common patterns to build on, it was easy to make things cloud-native&#xA;or shim in some devops to improve people&#39;s lives. But when everyone&#39;s doing&#xA;their own thing, and everyone&#39;s &#34;own thing&#34; is very much built-on some rigid tribal&#xA;patterns then it&#39;s hard to really move fast cause everyone isn&#39;t already moving&#xA;in the same direction.&#xA;&#xA;That made me realize that the first problem Forge needed to solve was in&#xA;providing a way for engineers to have filesystem-native data access in the&#xA;Cloud, where we are S3-first in our storage philosophy. I didn&#39;t need to figure&#xA;out a way for everyone to name a dataset, define the dataset in the first&#xA;place, and give a nice `my_dataset.load` that worked in python, bash, cpp, and&#xA;who knows what else.... I reframed the problem from &#34;how do engineers load up&#xA;the data&#34; to &#34;how do engineers have access to the data&#34;. The requirements of&#xA;the Cat Autonomy group was pretty simple: POSIX-compliant storage.&#xA;&#xA;My pathway to solving this problem is initially underway, I can&#39;t imagine it&#39;ll&#xA;be too difficult to setup for FSx instances for teams and give them an api to&#xA;run a Batch Job with the FSx mounted. From there, their code can load data from&#xA;`/mnt/fsx/&lt;whatever&gt;` just like they otherwise could be doing locally. Or maybe&#xA;FSx will let us setup mounts to very flexible mount points and their local&#xA;scripts will &#34;just work&#34; :shrugs:. I don&#39;t know the exact shape, but after&#xA;realizing the loading data is a big deal, I&#39;m thankful I have a narrower&#xA;problem to solve first.&#xA;&#xA;!!! note &#34;S3 Files&#34;&#xA;&#xA;    Literally yesterday, AWS launched &#34;S3 Files&#34; offering an NFS filesystem service over buckets. I&#39;m not sure if NFS is going to be a viable filesystem protocol for all of our use cases, but looks like we&#39;re not the only people who need the filesystem access patterns over S3.&#xA;&#xA;!!! warning &#34;A Future Problem - Canonical Reference&#34;&#xA;&#xA;    Another high-value thing Forge needs to solve is &#34;what is data&#34;. The data&#xA;    formats we have are not super simple, it&#39;s not just a set of SQL tables. We&#xA;    have files that relate to each other based on hard-filepath patterns, and those&#xA;    patterns are full of tribal knowledge and distributed processes. So a simple&#xA;    question like &#34;How do I use forge to access my data&#34; is hard. In Reman a data&#xA;    scientist would ask &#34;how do I use rada to access my data?&#34; and the answer is&#xA;    &#34;We use Kedro, and Kedro solved that problem for us via the Catalog&#34; but&#xA;    without Kedro, without 100% being in python (devs are also in embedded systems,&#xA;    cpp code, and more), without even consistent practices in the existing &#34;how do&#xA;    I access my data&#34; workflows, it&#39;s really impossible to systemetize and codify&#xA;    it. It is my next challenge to tackle though...&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Agents can miss obvious things too</title>
    <id>https://pype.dev/agents-can-miss-obvious-things-too/</id>
    <updated>2026-04-03T14:39:51Z</updated>
    <published>2026-04-03T14:39:51Z</published>
    <link href="https://pype.dev/agents-can-miss-obvious-things-too/" rel="alternate" type="text/html"></link>
    <summary type="text">I am working with MiniMax M.2 to vibe up some webapp ideas for Nexus and I just spent many minutes not having the app render correctly because the agent...</summary>
    <content type="text">&#xA;I am working with MiniMax M.2 to vibe up some webapp ideas for [[Nexus]] and I&#xA;just spent many minutes not having the app render correctly because the agent&#xA;mounted the wrong directory into the docker compose stack. I noticed it about 5&#xA;seconds after opening the file, but wasted nearly a half hour thinking it was a&#xA;docker issue in distrobox...&#xA;&#xA;!!! danger &#34;&#34;&#xA;&#xA;    Clankers are still just clankers man&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>The Irony of 10x</title>
    <id>https://pype.dev/the-irony-of-10x/</id>
    <updated>2026-03-26T06:00:50Z</updated>
    <published>2026-03-26T06:00:50Z</published>
    <link href="https://pype.dev/the-irony-of-10x/" rel="alternate" type="text/html"></link>
    <summary type="text">Agentic coding has been an exciting change to me over the last couple of months specifically. I&#39;ve been using AI tools for a few years now but something...</summary>
    <content type="text">&#xA;## Opener&#xA;&#xA;Agentic coding has been an exciting change to me over the last couple of months&#xA;specifically. I&#39;ve been using AI tools for a few years now but something really&#xA;shifted with Opus 4.5 as well as the tools/harnesses getting better and more&#xA;useful around the same time. I&#39;ve been influenced by people like Simon Willison&#xA;and Steve Yegge who have been on the forefront of agentic coding and [vibe&#xA;engineering](https://simonwillison.net/2025/Oct/7/vibe-engineering/) since the&#xA;dawn of ChatGPT and in my small circles of work I&#39;m definitely on the bloodiest&#xA;bleeding edge of the adoption of these practices. Are they the future? I don&#39;t&#xA;know - I tried to maintain a skeptical posture but until the bubble pops it&#39;s&#xA;looking like this is at least a direction the future of my line of work is&#xA;going.&#xA;&#xA;!!! danger &#34;&#34;&#xA;&#xA;    The tough part is mixing the new world of agentic coding with&#xA;    developers on wildly different points in the spectrum of adoption and maturity.&#xA;&#xA;Here&#39;s a short anecdote about what I mean...&#xA;&#xA;In a new project that I&#39;m on, I&#39;ve refactored/reimplemented a lot of legacy&#xA;code, producing about 140k lines of code, configuration, and&#xA;docs in about 2 months. It&#39;s an insane amount of &#34;product&#34; and I&#39;ve done it&#xA;entirely with agents. But I didn&#39;t do it with a handful of vanilla chat&#xA;sessions like &#34;Hey Copilot, reimplement this API, no mistakes&#34;. I&#39;ve been building&#xA;out my own process for using LLMs effectively. I have no actual idea besides my&#xA;own experience if what I&#39;m building is useful, but it feels pretty good -&#xA;agents for planning, building, reviewing, testing, etc. My &#34;harness&#34; includes&#xA;specialized agents and opinionated development workflows&#xA;to try to ensure that code is never one-shotted into production.&#xA;&#xA;The catch though is that I&#39;m working with a handful of developers and they are not&#xA;early-adopters or aggressive experimenters with these new agentic tools. Most&#xA;of them are still in Steve Yegge&#39;s stage 2 or 3 of AI coding as he&#39;s outlined&#xA;[in this medium&#xA;article introducing&#xA;GasTown](https://steve-yegge.medium.com/welcome-to-gas-town-4f25ee16dd04). They&#xA;open a chat session, and say yes or no to Opus. I&#39;ve been in-between stages&#xA;6 and 7 for a while now - managing multiple agentic sessions that themselves&#xA;run specialized subagents primarily for context management, although I don&#39;t&#xA;feel quite ready for full blown stage 8 (agents running agents running agents).&#xA;So this isn&#39;t me saying that I&#39;m&#xA;&#34;better&#34; than the guys I&#39;m working with, just the project we&#39;re on&#xA;together is now being touched by people on wildly different ends of the agentic&#xA;coding spectrum, and the project itself is an experiment to me of living in the &#34;New World&#34;.&#xA;&#xA;Finally the anecdote - I&#39;m getting PRs from guys in stages 2 and 3,&#xA;thousands of lines of code and config, that I know they are not necessarily&#xA;experts in, but they&#39;re producing that code with fairly vanilla practices. How&#xA;do I verify it? I know my own prompts, I know what agents generated my code, I know&#xA;the direction and prodding I gave as they&#39;re building, but all&#xA;I know in a PR review from someone else is the diff - not how they tested it&#xA;(unless of course there&#39;s tests, and there must be, but tests are only as good&#xA;as the tests are...), not the steering they gave, not the manual UAT validation&#xA;they did, or even the full intent... And ultimately I own the code they merge&#xA;because chances are I outlast their contract with the team. It&#39;s kind of a&#xA;scary thing to review and accept... do I trust my&#xA;agentic practices to validate their work? Cause I certainly don&#39;t trust myself&#xA;to validate it perfectly.&#xA;&#xA;!!! note &#34;a note about contractors&#34;&#xA;&#xA;    I&#39;m not implying anything about anyone who works contract, I think the facts is that contractors are typically dis-incentivized to really &#34;own&#34; something - an unfortunate consequence of the world.&#xA;&#xA;## This is about me, not everyone&#xA;&#xA;I want to make sure to reiterate the context of this post and my thoughts -&#xA;it&#39;s really about me. I&#39;m not saying anything here is true for anyone else, I&#39;m&#xA;not making predictions about tomorrow, and I&#39;m not a prominent FOSS developer or a&#xA;high-profile ex-FAANG engineer. I&#39;m not talking about every project under the sun.&#xA;I work at a big company, not a fast-paced startup. I work on internal tooling,&#xA;nothing that should even be seen outside our network. I&#39;m also a self-taught&#xA;developer, not a trained software engineer.&#xA;&#xA;As far as AI goes, lately I&#39;m mostly all in on Github Copilot&#xA;CLI with a sprinkling of Opencode. I&#39;m not using Claude Code or Codex which&#xA;seem to have their own communities around plugins and usage.&#xA;&#xA;And since we&#39;re so focused on me right now, the important thing to keep as the&#xA;backdrop for this post is my temperament and make-up. I&#39;m definitely made a&#xA;certain kind of way, not different than every single person necessarily, but&#xA;different enough, from enough people, to not blend in with the 9-5 guy who can&#xA;log out and not think about work until the morning (I&#39;m not saying that&#39;s a&#xA;strength either, my boundary problems are for another time).&#xA;&#xA;I feel an aggressive burden to solve problems and own those solutions, call it&#xA;white-knighting or a savior complex if you want, but I&#39;ve got enough of a&#xA;reputation at Caterpillar now (and anywhere else I&#39;ve worked) to become a go-to&#xA;person for more than I think is necessarily appropriate. And with that burden&#xA;I&#39;ll bring results - if a problem hooks into my brain it. will. be. solved. I&#xA;probably won&#39;t do the best most clean-code solution right out of the gate, but&#xA;I&#39;ll do whatever I can to find a solution.&#xA;&#xA;## Who I was before agents&#xA;&#xA;That is who I was before agents made code easy to produce. My first boss at&#xA;Caterpillar used the phrase &#34;tenacious learner&#34; to describe me in several&#xA;reviews. I kind of rejected the description because I basically refused to&#xA;believe that I was really any different, any harder of a worker, than my peers.&#xA;&#xA;But with almost a decade of experience in the corporate world, and some adult&#xA;perspective on my life, I think it&#39;s accurate... I am a harder worker, to my&#xA;detriment sometimes, than a fair number of people I&#39;ve worked with\*\*.&#xA;&#xA;I&#39;m not brilliant but I can focus for a long time in the right circumstances.&#xA;The gift of perseverance (or the curse of not being able to let something go,&#xA;depending on how you look at it) has led to blessing in my life in both reward&#xA;and skill.&#xA;&#xA;!!! note &#34;\*\*&#34;&#xA;&#xA;    There&#39;s nothing wrong with it either, Cat&#39;s somewhat noticed that work in my EOY reviews and I&#39;m certainly not against &#34;just doing your job&#34;.&#xA;&#xA;And then AI came along and with another set of the right circumstances&#xA;catalyzed a new way to work.&#xA;&#xA;## Leaning into &#34;Agentic Engineering&#34;&#xA;&#xA;I jumped onto experimenting with AI coding tools as soon as they became&#xA;available, but mostly I just tried vibe coding rather than using tools for real&#xA;engineering work. I vibed up an API at one of my jobs that went into production&#xA;way too early, with far too little validation, and it was scary to support it&#xA;from then on out. I also did the meme, vibe-coded a TODO app, and threw that&#xA;puppy into the internet without locking down my API endpoints... That was&#xA;before agents were quite as useful as they can be&#xA;now, but that experience along with a handful of other stepping stones (like&#xA;learning some real actual fundamentals about security) began to&#xA;give me confidence in using the AI as a tool, like my IDE is a tool, for&#xA;producing **solutions** that take the form of code.&#xA;&#xA;!!! note &#34;&#34;&#xA;&#xA;    As one-shot apps got better and better, and as I learned about scoping work&#xA;    more appropriately for agentic tools my confidence in them grew.&#xA;&#xA;There&#39;s quite a difference between &#34;Claude make me a todo app, no mistakes&#34; and&#xA;scoping out a solution in natural language, with some technical guardrails, and&#xA;having agents tackle the implementation methodically.&#xA;&#xA;## What actually changed&#xA;&#xA;What&#39;s actually changed for me is quite a lot... I haven&#39;t opened my IDE to&#xA;seriously write code for months now. I&#39;ve oscillated between Opencode and&#xA;Copilot CLI, leaning moreso into Copilot since it&#39;s an approved tool at work&#xA;and as of mid-February is quite good. Mentally I&#39;m approaching problems with a&#xA;little more thought on the front-end than before because prior to agents I&#xA;would think as I implemented. At the scale of work that I do, this was really&#xA;fine - working on CLI utilities to solve simple problems, developing an&#xA;iterative testing cycle for each problem that allowed me to move fast, and once&#xA;I found a groove I was cooking. But now I don&#39;t even need to find it, I open&#xA;Opencode or Copilot CLI with my Planner agent, describe what I want to happen and have&#xA;Opus or GPT scope out a plan for me. Usually there&#39;s some back and forth on&#xA;feature scoping, then I review a markdown file it produces, and once it looks&#xA;decent enough to me I say &#34;go&#34; and it goes.&#xA;&#xA;That works a lot better than I even care to admit because at the same time as&#xA;I&#39;ve been leaning harder into agents, I&#39;ve been building my own harness of&#xA;sorts - not a replacement for Copilot CLI or a competitor to Opencode, but&#xA;moreso an opinionated workflow spine that I force agents into to give strict&#xA;gates to the SDLC (software development lifecycle).&#xA;&#xA;!!! warning &#34;Problem Solving Workflows&#34;&#xA;&#xA;    Plan and implement is fine for a lot of things, and I do think it&#39;s only getting better. My harness,&#xA;    mentioned a few times around here before, called Nexus, is a set of agents and&#xA;    rules that I want the code I&#39;ll be responsible for to go through before it&#xA;    lands in production. That cycle isn&#39;t too complex, and there&#39;s only about&#xA;    10,000 similar tools to Nexus on Github trending right now. I&#39;ve thought about dropping my idea and picking up&#xA;    something more popular, like&#xA;    [superpowers](https://www.github.com/obra/superpowers) but at the moment I&#39;m&#xA;    continuing to develop on and lean into my own idea here.&#xA;&#xA;!!! note &#34;Mini post on Nexus&#34;&#xA;&#xA;    I keep saying a blog post is coming, but the high level of Nexus is that it&#39;s a task&#xA;    tracker with a CLI that agents use to advance a ticket through a plan -&gt; build&#xA;    -&gt; test -&gt; review -&gt; verify -&gt; merge lifecycle that is almost exactly how I&#xA;    would otherwise have solved a problem by hand. I think it needs work, I need to&#xA;    be harder on TDD methodlogies with agents, and work on verification gating a&#xA;    bit more (shoutout to [showboat](https://github.com/simonw/showboat) by Simon&#xA;    Willison) but overall it&#39;s a system of thinking that I already participate in&#xA;    so I&#39;m doing my best to farm out specific parts of my workflow to agents rather&#xA;    than trying to one-shot enterprise problems and solutions.&#xA;&#xA;!!! danger &#34;Who&#39;s doing the thinking?&#34;&#xA;&#xA;    I&#39;ve noticed that as I&#39;ve developed Nexus out though, I lean on the agents for&#xA;    more and more of my own thinking, and am trusting my problem solving&#xA;    **process** moreso than my actual problem solving abilities.&#xA;&#xA;## Hidden costs&#xA;&#xA;The cost of this increase in speed is a lack of familiarity - and the fallout&#xA;of lack of familiarity is hard to express. There&#39;s also many facets to it.&#xA;For me, the first facet is that Nexus helps me move fast, but as I&#39;ve leaned&#xA;into it for more and more of the planning, I&#39;m less and less familiar with the&#xA;state of the code. I find myself asking my reviewer agents in fresh sessions&#xA;often to explain it to me, and thankfully they&#39;re usually consistent, but&#xA;nonetheless I&#39;m still not intimately familiar with the code. And on Nexus it&#39;s&#xA;not a big deal, that&#39;s low stakes, it&#39;s just me and my workflow.&#xA;&#xA;I&#39;m using Nexus + Copilot at work and that feels like higher&#xA;stakes... I have my agents explain the status of our project and although they&#39;re&#xA;also somewhat consistent the thing that&#39;s scary is that other people are&#xA;working on that repo with me, and that&#39;s where another layer of complexity&#xA;manifests itself. If it&#39;s just me and my [[clankers]], let&#39;s go all day long,&#xA;rebuild, ask questions, etc... but I have other developers I rub shoulders with&#xA;now, and if they ask me a question what am I going to say? &#34;Hold on, let me prompt&#xA;my agent for you&#34; - it&#39;s LMGTFY on steroids. And the burden becomes if I&#xA;feel like I can own and support what those other developers push into the repo.&#xA;&#xA;## Murky responsibility boundaries&#xA;&#xA;Why do I own their work? Well for the third time, this post is pretty&#xA;self-centered and all about me, and my situation is that the other developers I&#xA;work with presently are all contractors. Their work agreement with Cat could&#xA;end at any second, for practically any reason. The incentive structure isn&#39;t&#xA;there for these guys who technically work for an agency... Their bonuses aren&#39;t&#xA;bigger (or even exist) if Cat performs well, there&#39;s no extra vacation days in&#xA;it for em (aye, contractors don&#39;t get vacation days anyways), and not that it&#39;s&#xA;a problem, moreso just the nature of the world we&#39;re in - but they&#39;re basically&#xA;mercenaries out to the highest bidder and I happen to know of **multiple times&#xA;where Cat lost a good person to a higher bidder**.&#xA;&#xA;So this isn&#39;t really me trying to be negative about contractors at all, I&#39;m&#xA;here for a pay-check as well but Cat at least gives me SOME incentive to work&#xA;hard with the goal of compensation regardless of how altruistic I feel in my&#xA;own circumstances.&#xA;&#xA;!!! note &#34;Incentive&#34;&#xA;&#xA;    Better ratings mean marginally better end-of-year salary increases, and I&#39;ve received some other awards that certainly give me pause about jumping ship to another long-term place even when things can be crazy at Cat.&#xA;&#xA;It&#39;s more than just the contrator-ownership dilema, I&#39;ve dug myself quite a&#xA;hole over the last 8-10 years, gaining a reputation that I think many would&#xA;appreciate, but for me only lately increases the stress. I don&#39;t need to parrot&#xA;every accolade I&#39;ve ever received, that&#39;s not the point, but to make the point&#xA;as clear as I can - I have a lot of respect from quite a few people at&#xA;Caterpillar. I&#39;m blessed to have that reputation, and it&#39;s not like I haven&#39;t&#xA;worked hard for it - but people talk about me in a way so flattering I feel&#xA;like the main character in a fictional story sometimes.&#xA;&#xA;In a fictional story I can check out the ending, hit up spark notes, or ask AI&#xA;how it ends... but there isn&#39;t an &#34;end&#34; in my real world scenario, there&#39;s only&#xA;tomorrow and I feel the pressure of not knowing what tomorrow holds now more&#xA;than ever.&#xA;&#xA;!!! danger &#34;&#34;&#xA;&#xA;    Being noticed is starting to feel more costly than rewarding...&#xA;&#xA;## Financial irony&#xA;&#xA;What&#39;s the cost? It&#39;s hard to get specific without writing a novel but here&#39;s&#xA;the TLDR - because I&#39;ve been pretty good at what I do I&#39;ve been able to do this&#xA;type of work outside my normal 9-5 responsibilities and with that extra work&#xA;has been some pretty great financial benefits. However with Cat changes,&#xA;responsibility increases, and now owning code that others (and their clankers)&#xA;write, the extra time I gained for myself is eaten-up and has been reclaimed by&#xA;the mega-corp... &#34;Exceeding expectations&#34; every year just meant the bar is&#xA;raised, the expectations are higher, the time-commitment requirement is higher,&#xA;and as I&#39;ve had to meet the requirements of both the new world and the curse of&#xA;being noticed, I&#39;ve lost the time for the extra work... For years I&#39;ve realized&#xA;the benefit of my own skills and drive, but the irony of agents (and a handful&#xA;of other things) is that with the dramatic increase in expectations, not only&#xA;on me but on those I work with and therefore their output, I don&#39;t get to&#xA;realize the benefits of my own gifts anymore.&#xA;&#xA;## Meaning and fatigue&#xA;&#xA;I feel very torn because the work I&#39;ve been called into with Cat is good, I&#xA;said in [[cat-autonomy-2-0]] that autonomy will save people&#39;s lives. I love&#xA;getting to participate in that mission, it&#39;s the primary reason I didn&#39;t jump&#xA;ship to try to maintain the levels, and type, of work I was doing before... But&#xA;in a few short months the mission is being drowned out by expectations and&#xA;requirements that are so high I&#39;m losing the grip on my own life.&#xA;&#xA;## Open questions&#xA;&#xA;That leads me to questions that I can&#39;t answer, the question I ask daily now of&#xA;&#34;What about tomorrow?&#34;. What will agents do for us tomorrow, what problems will&#xA;be solved, what bugs will I create (by agents of course because I&#39;ve never&#xA;written a bug by hand in my whole life \s). If I stopped using agents would&#xA;people still be impressed? Would it even matter?&#xA;&#xA;## Fin&#xA;&#xA;I&#39;m certainly not anti-AI, it&#39;s typing all my code. I&#39;m not anti-collaboration,&#xA;although I do wish I could work alone with just my clanker-army to worry about.&#xA;I&#39;m not sure what I am anymore though... AI has changed how I work, what I work&#xA;on, and who I work with... Everything has changed in such a short period of&#xA;time and like the ending of this post, it&#39;s pretty jarring.&#xA;&#xA;!!! danger &#34;&#34;&#xA;&#xA;    Death comes to us all - James Acaster.&#xA;&#xA;Thanks for reading.&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Remote Terraform State Requires Working Traefik… DUH!</title>
    <id>https://pype.dev/remote-terraform-state-requires-working-traefik-duh/</id>
    <updated>2026-03-23T08:12:25Z</updated>
    <published>2026-03-23T08:12:25Z</published>
    <link href="https://pype.dev/remote-terraform-state-requires-working-traefik-duh/" rel="alternate" type="text/html"></link>
    <summary type="text">I&#39;m working on some spring cleaning in my homelab and backed myself into a hilarious corner yesterday. I use Open Tofu for any of my Terraform needs now, and...</summary>
    <content type="html">&lt;p&gt;I&amp;rsquo;m working on some spring cleaning in my homelab and backed myself into a&#xA;hilarious corner yesterday. I use Open Tofu for any of my Terraform needs now,&#xA;and although I don&amp;rsquo;t manage a ton with terraform, I do manage all my cloudflare&#xA;stuff with it. I decided I wanted to use my own minio instance as the s3 remote&#xA;state backend for my workspaces so I could rely on my typical NAS data&#xA;backup/retention workflow for the buckets in case anything went wrong, as&#xA;opposed to a local state file that I&amp;rsquo;m not taking a lot of precautions with.&#xA;Well during my Spring Cleaning I was working towards replacing ingress into my&#xA;home network with Cloudflare tunnels and in the midst of that update I took&#xA;down traefik, no matter a simple &amp;rsquo;tofu apply&amp;rsquo; should get me right back to&#xA;working order&amp;hellip;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;╷&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;Error&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;Error&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;inspecting&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;states&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;the&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;s3&amp;#34;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;backend&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;     &lt;span class=&#34;k&#34;&gt;operation&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;error&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;S3&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;ListObjectsV2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;https&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;response&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;error&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;StatusCode&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;404&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;RequestID&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;HostID&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;api&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;error&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;NotFound&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;Not&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;Found&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Hilarious problem with thankfully an easy fix&amp;hellip; downloading the state file&#xA;from Minio wasn&amp;rsquo;t a big deal since the container was still running without&#xA;issue, and placing the state file in the folder to use as the local state&#xA;solution for the interim went totally smooth, but this highlights the set of&#xA;interdependencies I&amp;rsquo;m creating for myself and as I take the next few days/weeks&#xA;to do some spring cleaning I&amp;rsquo;m hoping I can separate out the external ingress&#xA;from internal with a bit more clear boundaries so that I never lock myself out&#xA;of a workflow I only execute on my LAN in the first place!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>To Live In A World Without AI</title>
    <id>https://pype.dev/to-live-in-a-world-without-ai/</id>
    <updated>2026-03-22T14:50:38Z</updated>
    <published>2026-03-22T14:50:38Z</published>
    <link href="https://pype.dev/to-live-in-a-world-without-ai/" rel="alternate" type="text/html"></link>
    <summary type="text">I&#39;m finding lately that I wish we could go back to pre-ChatGPT... A world without a code-gen easy button, where &#34;easy&#34; was LSP autocomplete, where tools were...</summary>
    <content type="html">&lt;p&gt;I&amp;rsquo;m finding lately that I wish we could go back to pre-ChatGPT&amp;hellip; A world&#xA;without a code-gen easy button, where &amp;ldquo;easy&amp;rdquo; was LSP autocomplete, where tools&#xA;were at my fingertips rather than remote inference endpoints, and where I and&#xA;everyone I worked with, was paid and judged based on what we could produce with&#xA;our own 2 hands, even if &lt;code&gt;ctrl + c&lt;/code&gt; and &lt;code&gt;ctrl + v&lt;/code&gt; was sometimes a common set of keys&amp;hellip; it&#xA;sure beat answering &amp;ldquo;yes&amp;rdquo; to a robot every 38 seconds.&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>paynepride dot com outage on vacation</title>
    <id>https://pype.dev/paynepride-dot-com-outage-on-vacation/</id>
    <updated>2026-03-16T13:21:31Z</updated>
    <published>2026-03-16T13:21:31Z</published>
    <link href="https://pype.dev/paynepride-dot-com-outage-on-vacation/" rel="alternate" type="text/html"></link>
    <summary type="text">The day after I leave for vacation I start getting SSL errors on every homelab service I host for myself and others. The culprit was my Cloudflare API token...</summary>
    <content type="html">&lt;p&gt;The day after I leave for vacation I start getting SSL errors on every homelab&#xA;service I host for myself and others. The culprit was my Cloudflare API token&#xA;expiring. It was easy to find the 403s in the logs for Traefik (thank goodness&#xA;for Tailscale getting me into the lab from afar). The solution was to rotate the&#xA;API token, replace the value in Traefik&amp;rsquo;s .env file, and hit it with the &amp;ldquo;just&#xA;deploy&amp;rdquo; button. Now I don&amp;rsquo;t know why this expired - the key looks like it has&#xA;no expiration to me - and I&amp;rsquo;m too tired from the beach to dig in further.&#xA;Until next time, I expect this error to come back March 16 2027 I suppose.&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>My Thoughts on Beads</title>
    <id>https://pype.dev/my-thoughts-on-beads/</id>
    <updated>2026-03-03T05:00:47Z</updated>
    <published>2026-03-03T05:00:47Z</published>
    <link href="https://pype.dev/my-thoughts-on-beads/" rel="alternate" type="text/html"></link>
    <summary type="text">Steve Yegge is a pretty well-known individual in the tech field, having been around for a long time at some of the larger companies. He&#39;s making quite a...</summary>
    <content type="text">&#xA;[Steve Yegge](https://en.wikipedia.org/wiki/Steve_Yegge) is a pretty well-known individual in the tech field, having been&#xA;around for a long time at some of the larger companies. He&#39;s making quite a&#xA;splash in the agentic coding world as well. I&#39;ve appreciated Steve&#39;s posts and&#xA;projects lately and wanted to put some thoughts on one called&#xA;[beads](https://github.com/steveyegge/beads).&#xA;&#xA;## Beads&#xA;&#xA;Beads is an issue tracker with links - issues relate to and block each other,&#xA;but agents use beads to keep track of information and dependencies without&#xA;storing it in their context 100% of the time. It seems like a very popular and&#xA;useful tool - but I am not using it, and that&#39;s what I wanted to capture... why&#xA;not?&#xA;&#xA;The answer for me is about **where** the organization layer is for the&#xA;developer. Beads exists in a single repo - it&#39;s a system-wide CLI but you &#39;bd&#xA;init&#39; in a git repo, and beads uses the `.git/` folder, worktrees, [dolt](https://docs.dolthub.com/), and some&#xA;git hooks to operate within that git repo. Outside the repo, it takes another&#xA;tool to tie together all the beads databases you might have.&#xA;&#xA;For me, I&#39;m hardly &#34;in&#34; a git repo anymore. My workflow is that when I have&#xA;something to work on, I create a &#34;workspace&#34; ([self-defined concept](https://pypeaday.github.io/dotfiles/terminal/workspaces/#installation)) which is&#xA;just a folder on my filesystem where I check-out git worktrees from any of the&#xA;repos related to the work I&#39;m doing. Sometimes it&#39;s 1 worktree from 6 repos,&#xA;sometimes it&#39;s 6 worktrees from 1 repo for parallel work...&#xA;&#xA;So because I like to organize myself in this way, beads is already &#34;out&#34; for&#xA;me. That&#39;s the main reason - I don&#39;t have any real technical issues with beads&#xA;or any criticism, it just is designed for a workflow that is not how I work.&#xA;&#xA;This is why I&#39;m building [[nexus]], something I hope to be able to put out&#xA;there &#34;soon&#34;. It won&#39;t be as general-purpose as beads, but my goal with it is&#xA;to be plug-and-play for any agentic harness (copilot cli, claude code,&#xA;opencode, etc.). It&#39;s a challenge thinking about it as a personal tool but also&#xA;as a tool to share someday, but agentic coding is making it possible to make&#xA;some cool shareable stuff and I&#39;m excited for my own workflow-task-manager to&#xA;mature and at least become something useful to me (it already is, but building&#xA;the plane in the air makes it kind of hard to enjoy the plane).&#xA;&#xA;### Credit&#xA;&#xA;- banner image from ChatGPT&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Forge Ahead</title>
    <id>https://pype.dev/forge-ahead/</id>
    <updated>2026-02-17T05:14:15Z</updated>
    <published>2026-02-17T05:14:15Z</published>
    <link href="https://pype.dev/forge-ahead/" rel="alternate" type="text/html"></link>
    <summary type="text">Yesterday&#39;s reflection-contentment-and-work has a second-part this morning. As I was wrapping up a project I didn&#39;t realize the closed-off-ness of leaving......</summary>
    <content type="text">&#xA;Yesterday&#39;s [[reflection-contentment-and-work]] has a second-part this morning.&#xA;As I was wrapping up a project I didn&#39;t realize the closed-off-ness of&#xA;leaving... I handed in some notes, and mid-message to someone the clock struck&#xA;midnight and I was locked out. It&#39;s fitting to be honest, and now in the wake&#xA;of yesterday&#39;s contentment post, experiencing some more loss than I expected,&#xA;today we forge ahead.&#xA;&#xA;My main focus for work now is a project I will refer to as `forge`. It is what&#xA;I will bring to Caterpillar Autonomy but I can only build it thanks to the&#xA;gifts and experience God has given me. The thing I want to put on paper is a&#xA;short list of experiences I think God in his sovereignty, gave me over the last&#xA;few years and what they provide for me for Forge.&#xA;&#xA;## Cat Reman Platform&#xA;&#xA;One of the first things that comes to mind is another project I was sad to&#xA;lose: a platform I started for an analytics team in Cat Reman. That began as a&#xA;simple python cli to automate some developer operations that was otherwise a&#xA;dozen clicks through the AWS console. Using [boto3] and some simple python I&#xA;gave that team the start of some real velocity gains. Eventually that grew into&#xA;a larger kubernetes-based service where the data science operations: code quality,&#xA;deployment, updates, webapps, etc. were all handled by our platform. It wasn&#39;t&#xA;perfect, it wasn&#39;t self-contained, it was a set of things kind of glued&#xA;together with systems and scripts, but it worked, it works today and is under&#xA;fantastic ownership.&#xA;&#xA;What I learned just from starting that cli was to be passionate about solving&#xA;problems. No one asked me to make it, but it needed made, and the team is in&#xA;such a better place for me having started it.&#xA;&#xA;## Kedro and OpenShift&#xA;&#xA;Another short project I was able to participate in a few years ago was leading&#xA;a data-syncronization task into a fiery horrific crash that lasted weeks -&#xA;neigh months longer - than was necessary or appropriate... The details aren&#39;t&#xA;relevant - I was the lead dev in a new place tasks with syncing up data between&#xA;2 applications. Ultimately, could&#39;ve been a python script but I over-designed a&#xA;kedro-based solution because of some requirements I misunderstood. Part of that&#xA;misunderstanding was not knowing how to get the requirements I needed, but they&#xA;weren&#39;t provided in full, I didn&#39;t know any better, so for weeks we were a&#xA;corporate meme trying to use python to update a database that no one on our&#xA;team understood if we were allowed to write to.... It was very confusing.&#xA;&#xA;But what I learned was a lot about gathering requirements, questioning&#xA;assumptions, and the importance of understanding your constraints as fully as&#xA;possible as early as possible.&#xA;&#xA;## A Real Platform&#xA;&#xA;Then one of the biggest blessings I see for Forge, is the experience I&#39;ve&#xA;gotten recently with AWS at scale... Not 1 or 2 services created with&#xA;Medium.com copy pasta tutorials from docs... but experience working in a large&#xA;project across many accounts, supporting several teams, using a wide variety of&#xA;technologies from Terraform to Kubernetes.&#xA;&#xA;On this project I learned about practical system design and gained a lot of&#xA;confidence in supporting systems that are complicated... I&#39;m not the smartest&#xA;guy in the world but I&#39;m no dummy, and even while lacking fluency in the system&#xA;I was supporting on this project I learned a lot of troubleshooting skills and&#xA;gained confidence in my ability to troubleshoot complex systems.&#xA;&#xA;I&#39;ll need this for Forge - which will break certainly, but I&#39;ll be there to fix&#xA;it and I&#39;m sure I can because I&#39;ve done these other things.&#xA;&#xA;## Fin&#xA;&#xA;The Lord has been with me through these projects - he has certainly blessed me&#xA;with a skillset and personality that lends itself to being really useful in the&#xA;Tech world I&#39;ve landed in (which is a whole &#39;nother story of God&#39;s sovereignty&#xA;and provision). I am very grateful for the swath of experience I&#39;ve gotten over&#xA;the last 8 years or so, and this season I&#39;m in of change is rocking me a little&#xA;more than I anticipated but by God&#39;s grace I think I see the purpose, or at&#xA;least **a** purpose, and I pray I am making the choices for work he wants me to&#xA;make.&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Kubernetes External Secrets Operator</title>
    <id>https://pype.dev/kubernetes-external-secrets-operator/</id>
    <updated>2026-02-10T07:48:34Z</updated>
    <published>2026-02-10T07:48:34Z</published>
    <link href="https://pype.dev/kubernetes-external-secrets-operator/" rel="alternate" type="text/html"></link>
    <summary type="text">I wanted to put a short demo together of using External Secrets Operator (ESO) to expose secrets from a vault (like Hashicorp Vault, AWS Secrets Manager,...</summary>
    <content type="text">&#xA;I wanted to put a short demo together of using External Secrets Operator (ESO)&#xA;to expose secrets from a vault (like Hashicorp Vault, AWS Secrets Manager, etc)&#xA;to services running in kubernetes&#xA;&#xA;Demo code is [here in this github repo](https://github.com/pypeaday/blog-kubernetes-external-secrets-operator-demo)&#xA;&#xA;This post is a high level overview of the components, see the repo for the full example.&#xA;&#xA;## Setup&#xA;&#xA;- [[docker]] for containerized development&#xA;- [[kind]] for setting up a quick cluster&#xA;- [[kubectl]] for accessing the cluster&#xA;- [[helm]] for installing ArgoCD and ESO&#xA;&#xA;- and then [justfile](https://github.com/casey/just) is there to wrap the commands to easier execution&#xA;&#xA;## Step 0 - Vault&#xA;&#xA;- for the demo we&#39;ll setup Hashicorp Vault in docker compose to easily bring it&#xA;  up and down&#xA;- and the init-script is in the repo - it uses curl to make some secrets in&#xA;  vault that we&#39;ll reference later&#xA;&#xA;```yml&#xA;services:&#xA;  vault:&#xA;    image: hashicorp/vault:1.18&#xA;    container_name: vault&#xA;    ports:&#xA;      - &#34;58200:8200&#xA;    environment:&#xA;      VAULT_DEV_ROOT_TOKEN_ID: root&#xA;      VAULT_DEV_LISTEN_ADDRESS: 0.0.0.0:8200&#xA;    volumes:&#xA;      - vault-data:/vault/file&#xA;    cap_add:&#xA;      - IPC_LOCK&#xA;    command: server -dev -dev-root-token-id=root&#xA;&#xA;volumes:&#xA;  vault-data:&#xA;```&#xA;&#xA;- bringing up the vault instance is a simple `docker compose up` (use the just recipes which some `curl` commands for checking status etc.)&#xA;&#xA;```bash&#xA;curl -s http://localhost:58200/v1/sys/health | jq .  # or just vault-status&#xA;{&#xA;  &#34;initialized&#34;: true,&#xA;  &#34;sealed&#34;: false,&#xA;  &#34;standby&#34;: false,&#xA;  &#34;performance_standby&#34;: false,&#xA;  &#34;replication_performance_mode&#34;: &#34;disabled&#34;,&#xA;  &#34;replication_dr_mode&#34;: &#34;disabled&#34;,&#xA;  &#34;server_time_utc&#34;: 1770893657,&#xA;  &#34;version&#34;: &#34;1.18.5&#34;,&#xA;  &#34;enterprise&#34;: false,&#xA;  &#34;cluster_name&#34;: &#34;vault-cluster-acfb9930&#34;,&#xA;  &#34;cluster_id&#34;: &#34;4d9162f4-e501-371b-7f94-bd60052b40a3&#34;,&#xA;  &#34;echo_duration_ms&#34;: 0,&#xA;  &#34;clock_skew_ms&#34;: 0,&#xA;  &#34;replication_primary_canary_age_ms&#34;: 0&#xA;}&#xA;```&#xA;&#xA;## Step 1 - App&#xA;&#xA;- We need an app that requires secrets&#xA;- app code in repo, essentially it&#39;s a python webserver to show the vault&#xA;  values (obviously this would expose real secrets so it&#39;s just a demo)&#xA;- Below is one of the endpoints in the vibe-coded app, just to illustrate that&#xA;  we&#39;re going to give secrets to the app as environment variables (or as mounted&#xA;  files!)&#xA;- In the repo, the app is included and there&#39;s a `just build` which builds the docker image&#xA;- There is also `just deploy` which handles loading the image into `kind`&#39;s image cache&#xA;&#xA;```py&#xA;&#xA;# example route from demo-app - see git repo&#xA;@app.get(&#34;/env&#34;, response_class=HTMLResponse)&#xA;def show_env():&#xA;    # ESO brings Vault secrets into environment variables&#xA;    env_vars = dict(os.environ)&#xA;&#xA;    # Sort by category, then by key&#xA;    sorted_items = sorted(env_vars.items(), key=lambda x: (classify_env(x[0]), x[0]))&#xA;&#xA;    cards = &#34;&#34;.join(create_card(k, v) for k, v in sorted_items)&#xA;&#xA;    secret_count = sum(1 for k in env_vars if k in SECRET_KEYS)&#xA;    config_count = sum(1 for k in env_vars if k in CONFIG_KEYS)&#xA;    system_count = len(env_vars) - secret_count - config_count&#xA;&#xA;    html = HTML_TEMPLATE.format(&#xA;        cards=cards,&#xA;        secret_count=secret_count,&#xA;        config_count=config_count,&#xA;        system_count=system_count,&#xA;    )&#xA;&#xA;    return HTMLResponse(content=html)&#xA;&#xA;def read_mounted_files(directory: str) -&gt; dict:&#xA;    &#34;&#34;&#34;Read all files from a mounted directory.&#34;&#34;&#34;&#xA;    files_data = {}&#xA;    if os.path.exists(directory) and os.path.isdir(directory):&#xA;        for filename in os.listdir(directory):&#xA;            filepath = os.path.join(directory, filename)&#xA;            if os.path.isfile(filepath):&#xA;                try:&#xA;                    with open(filepath, &#34;r&#34;) as f:&#xA;                        files_data[filename] = f.read().strip()&#xA;                except Exception as e:&#xA;                    files_data[filename] = f&#34;&lt;Error reading file: {e}&gt;&#34;&#xA;    return files_data&#xA;&#xA;```&#xA;&#xA;## Step 2 - Cluster&#xA;&#xA;- use `kind` to bring up a cluster&#xA;- this will start a few docker containers to act as your control-plane and workers&#xA;&#xA;```yml&#xA;# kind-config.yml&#xA;kind: Cluster&#xA;apiVersion: kind.x-k8s.io/v1alpha4&#xA;name: eso-demo&#xA;nodes:&#xA;  - role: control-plane&#xA;    extraPortMappings:&#xA;      - containerPort: 30080&#xA;        hostPort: 58080&#xA;        protocol: TCP&#xA;  - role: worker&#xA;```&#xA;&#xA;```&#xA;kind create cluster --config kind-config.yaml --name eso-demo&#xA;```&#xA;&#xA;## Step 3 - External Secrets Operator&#xA;&#xA;- installed with [[helm]] from the official helm chart&#xA;- NOTE: this is the Operator, not the secrets... this is the thing which goes&#xA;  to the secrets backend and creates kubernetes secrets&#xA;&#xA;```&#xA;helm repo add external-secrets https://charts.external-secrets.io 2&gt;/dev/null || true&#xA;helm repo update&#xA;helm install external-secrets external-secrets/external-secrets \&#xA;  --namespace external-secrets \&#xA;  --create-namespace \&#xA;  --wait&#xA;```&#xA;&#xA;In the repo this is mostly `just eso-install`&#xA;&#xA;## Step 3.5 - Secretstore&#xA;&#xA;- You need a `clustersecretstore` to be the place that ESO puts secrets&#xA;&#xA;```&#xA;apiVersion: external-secrets.io/v1&#xA;kind: ClusterSecretStore&#xA;metadata:&#xA;  name: vault-backend&#xA;spec:&#xA;  provider:&#xA;    vault:&#xA;      server: &#34;http://10.10.0.1:58200&#34;&#xA;      path: &#34;secret&#34;&#xA;      version: &#34;v2&#34;&#xA;      auth:&#xA;        tokenSecretRef:&#xA;          name: vault-token&#xA;          key: token&#xA;          namespace: external-secrets&#xA;&#xA;```&#xA;&#xA;## Step 4 - Secrets&#xA;&#xA;- Secrets go in the `clustersecretstore`&#xA;  - in this example it&#39;s called &#39;vault-backend&#39;&#xA;- In the demo we can just `kubectl apply -f &lt;manifest&gt;` to deploy the secret to&#xA;  the cluster&#xA;- In practice this should be handled by something more mature than raw-doggin&#xA;  kubectl commands&#xA;&#xA;```yml&#xA;# manifests/external-secrets.yml&#xA;---&#xA;apiVersion: external-secrets.io/v1&#xA;kind: ExternalSecret&#xA;metadata:&#xA;  name: demo-app-secrets&#xA;  namespace: default&#xA;spec:&#xA;  refreshInterval: &#34;10s&#34;&#xA;  secretStoreRef:&#xA;    kind: ClusterSecretStore&#xA;    name: vault-backend&#xA;  target:&#xA;    name: demo-app-secrets&#xA;    creationPolicy: Owner&#xA;  data:&#xA;    - secretKey: DATABASE_PASSWORD&#xA;      remoteRef:&#xA;        key: secret/data/demo-app/secrets&#xA;        property: database_password&#xA;    - secretKey: API_KEY&#xA;      remoteRef:&#xA;        key: secret/data/demo-app/secrets&#xA;        property: api_key&#xA;```&#xA;&#xA;## Step 4.1 - Files&#xA;&#xA;- ESO supports mounting files to containers as well through special `ExternalSecret` resources&#xA;- One of the example seecrets is a TLS certificate&#xA;&#xA;```yml&#xA;# manifests/external-secrets-files.yml&#xA;---&#xA;# File-based ExternalSecret for TLS certificates&#xA;# These will be mounted as files in /etc/secrets/&#xA;apiVersion: external-secrets.io/v1&#xA;kind: ExternalSecret&#xA;metadata:&#xA;  name: demo-app-tls-files&#xA;  namespace: default&#xA;spec:&#xA;  refreshInterval: &#34;10s&#34;&#xA;  secretStoreRef:&#xA;    kind: ClusterSecretStore&#xA;    name: vault-backend&#xA;  target:&#xA;    name: demo-app-tls-files&#xA;    creationPolicy: Owner&#xA;    # Template to ensure proper file formatting&#xA;    template:&#xA;      type: Opaque&#xA;      data:&#xA;        tls.crt: &#34;{{ .tls_crt }}&#34;&#xA;        tls.key: &#34;{{ .tls_key }}&#34;&#xA;  data:&#xA;    - secretKey: tls_crt&#xA;      remoteRef:&#xA;        key: secret/data/demo-app/tls-files&#xA;        property: tls.crt&#xA;    - secretKey: tls_key&#xA;      remoteRef:&#xA;        key: secret/data/demo-app/tls-files&#xA;        property: tls.key&#xA;```&#xA;&#xA;- Notice how there&#39;s a `spec.target.template` which templates out the file&#xA;  contents from the secret contents&#xA;&#xA;## Step 5 - Helm Chart&#xA;&#xA;- This isn&#39;t about setting up a helm chart so I&#39;m not going to explain a lot&#xA;  but the working example is simple, not secure, and in the repo&#xA;- The helm chart renders manifests - I&#39;ve paired one down and added comments to&#xA;  the relevant things&#xA;- The thing to just take note of is the reference of the secrets in the `envFrom` section&#xA;&#xA;```yml&#xA;# deployment.yml&#xA;apiVersion: apps/v1&#xA;kind: Deployment&#xA;metadata:&#xA;  annotations:&#xA;    meta.helm.sh/release-name: demo-app&#xA;    meta.helm.sh/release-namespace: default&#xA;  name: demo-app&#xA;  namespace: default&#xA;spec:&#xA;  replicas: 1&#xA;  template:&#xA;    metadata:&#xA;      labels:&#xA;        app.kubernetes.io/instance: demo-app&#xA;        app.kubernetes.io/name: demo-app&#xA;    spec:&#xA;      containers:&#xA;        - envFrom:&#xA;            - secretRef:&#xA;                name: demo-app-secrets # name of example secret from section 4&#xA;            - secretRef:&#xA;                name: demo-app-config # another example in the repo&#xA;          image: demo-app:latest # the image you built and loaded into kind - simple &#39;just&#39; recipe in the repo&#xA;          imagePullPolicy: Never&#xA;          name: demo-app&#xA;          volumeMounts:&#xA;            - mountPath: /etc/secrets&#xA;              name: secrets-volume&#xA;              readOnly: true&#xA;            - mountPath: /etc/config&#xA;              name: configs-volume&#xA;              readOnly: true&#xA;      volumes:&#xA;        - name: secrets-volume&#xA;          secret:&#xA;            defaultMode: 420&#xA;            secretName: demo-app-tls-files # example secret file from section 4.1&#xA;        - name: configs-volume&#xA;          secret:&#xA;            defaultMode: 420&#xA;            secretName: demo-app-config-files&#xA;```&#xA;&#xA;## Step 5.1 - Deploy&#xA;&#xA;- We can deploy the demo-app from the git repo to the cluster&#xA;- For a local demo a few things happen&#xA;  - local image build&#xA;  - loading that image into [[kind]] (`kind` doesn&#39;t have access to your host&#39;s docker image cache, so images need to be loaded into the cluster cache)&#xA;- `just deploy` takes care of this for you, read the recipe in the repo if&#xA;  you&#39;re interested in more there, the focus of this post and example are to&#xA;  briefly show how to use ESO though&#xA;&#xA;## Step 6 - Profit&#xA;&#xA;The example app just displays things that are mounted in - totally vibe-coded&#xA;to illustrate the secrets mounting, not the appropriate way to leak secrets.&#xA;&#xA;![20260210233804_614254b7.png](https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20260210233804_614254b7.png)&#xA;&#xA;![20260210233828_19852225.png](https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20260210233828_19852225.png)&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Cat Autonomy 2.0</title>
    <id>https://pype.dev/cat-autonomy-2-0/</id>
    <updated>2026-02-09T06:07:12Z</updated>
    <published>2026-02-09T06:07:12Z</published>
    <link href="https://pype.dev/cat-autonomy-2-0/" rel="alternate" type="text/html"></link>
    <summary type="text">I wrote about my new role new-job-caterpillar-autonomy a bit a couple weeks ago during an insanely busy time - having just started the role and wrapping up...</summary>
    <content type="text">&#xA;I wrote about my new role [[new-job-caterpillar-autonomy]] a bit a couple weeks&#xA;ago during an insanely busy time - having just started the role and wrapping up&#xA;what ended up being side-work, paired with some sleep-deprived ADHD hyperfocus&#xA;on my new responsibilities and [[nexus]], that post is less of an update and&#xA;more of a mind-dump. This post is meant to be a calmer update about my upcoming&#xA;time with Caterpillar Autonomy.&#xA;&#xA;It starts, like all good stories, with Caterpillar&#39;s RTO (return to office)&#xA;mandate and how it has affected a lot of people negatively (in my opinion). I&#xA;haven&#39;t seen one positive remark about it fromanyone making less than $250k a&#xA;year + Bonus + Equity if you catch my drift...&#xA;&#xA;I know of people who really did lose their jobs at the end of 2025 for refusing&#xA;to move. My story with RTO is covered elsewhere, I&#39;d been blessed with remote&#xA;work and was even secure in a remote position in the face of Caterpillar being&#xA;willing to fire me [[after-exceeding-expectations-for-4-years]].&#xA;&#xA;But time passes and life happens, and the sovereign Lord brought me to this current&#xA;circumstance: where I&#39;m fully committed to Caterpillar Autonomy, and it&#xA;feels weird to say it. I&#39;m going to skip the RTO details, if you know you know.&#xA;Where I&#39;m at right now is on the other side (or very nearly on the other side)&#xA;of a choice I didn&#39;t feel freedom to make because it came from a conviction.&#xA;&#xA;The manager of the group I&#39;m in told me a story about working for another&#xA;mining company, where he was managing mines in the Congo. These mines can be in&#xA;the most remote of remote places on earth - in cultures where human life is&#xA;definitely treated differently than in the first-world midwest USA. Operators of&#xA;these huge mining trucks in these parts of the world can be smoking meth in the&#xA;cabs - which obviously leads to unsafe operation. Safety of the mines&#xA;themselves can be a second-thought as well, they collapse and then the people&#xA;inside have to be excavated out. Sean told me he had come back to work after a&#xA;weekend just to be told, as if it was no big deal, that &#34;Motombu died&#34; and to&#xA;find another operator. Very crass attitude towards human life...&#xA;&#xA;I&#39;m still pretty frustrated at Caterpillar for how they&#39;ve handled RTO (and&#xA;corporitisms like &#34;Caterpillar family&#34; and &#34;we bleed Cat yellow&#34; are&#xA;distracting nonsense), and part of me wants to leave still over the personal&#xA;offence, but Caterpillar will make the safest mining equipment, without a&#xA;doubt. And given that Cat will make the safest equipment then the story I was told and&#xA;the mission I couldn&#39;t help but believe in is that rolling out good autonomy&#xA;software and solutions to these remote mines will save lives.&#xA;&#xA;!!! warning &#34;&#34;&#xA;&#xA;    I&#39;m obviously not like superman or anything, but something feels better about enabling good autonomy rather than supporting an online sales platform, or working for a bank...&#xA;&#xA;I was invited (coerced?) into that mission - and my role in it is enabling the&#xA;Autonomy group to manage data for their software stack. I get to help these&#xA;engineers be experts in the things they&#39;re experts in by offloading some&#xA;operational overhead (data movement, pipelineing, infrastructure and devops,&#xA;etc.) so that they can produce the best autonomy software on the planet.&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Learning How To Agent</title>
    <id>https://pype.dev/learning-how-to-agent/</id>
    <updated>2026-02-03T05:50:33Z</updated>
    <published>2026-02-03T05:50:33Z</published>
    <link href="https://pype.dev/learning-how-to-agent/" rel="alternate" type="text/html"></link>
    <summary type="text">I&#39;ve been using AI tools for codegen for a few years now, but not super heavily. I either use the in-line copilot stuff, which is like LSP on seteroids, or I...</summary>
    <content type="text">&#xA;## Introduction &amp; Background&#xA;&#xA;I&#39;ve been using AI tools for codegen for a few years now, but not super&#xA;heavily. I either use the in-line copilot stuff, which is like LSP on&#xA;seteroids, or I have gone all the way to the other side of full on vibecoding&#xA;with Windsurf. That&#39;s been fun enough, but not super fulfilling and at the end&#xA;of that I either have a simple webapp that does what I want but I don&#39;t&#xA;understand, or else a half-broken thing I tried to understand but couldn&#39;t&#xA;prompt in the right direction.&#xA;&#xA;!!! note &#34;One Caveat&#34;&#xA;&#xA;    My one caveat with Windsurf, which is a full IDE that I don&#39;t have a lot of comfortable navigation in due to all the Cascade keybindings clobbaring my own keymaps - is that with a HEAVY spec, it&#39;s done will with the Claude models at implementing a real idea I have. It&#39;s closer to vibe-engineering than vibe-coding, but that&#39;s my only instance, the rest of my Windsurf usage is &#34;make me a cool app - no mistakes&#34;&#xA;&#xA;This year it feels like some tools exploded and&#xA;I mentioned this in [[new-job-caterpillar-autonomy]]. I&#39;ve been using&#xA;[opencode](https://opencode.ai) a lot over the last few weeks and have iterated&#xA;many times already on a system of work that I&#39;m trying to lean into for&#xA;improving my efficiency.&#xA;&#xA;## The Problem Space&#xA;&#xA;My desire for a great Developer Experience is years old now, shout out to&#xA;ThePrimeagen for his [FEM&#xA;course](https://frontendmasters.com/courses/developer-productivity-v2/) and&#xA;[Waylon Walker](https://waylonwalker.com) for being a constant source of&#xA;encouragement to be the best developer I can be. I sometimes (often) get&#xA;tunnel-visioned on developer-productivity initiatives and lose the forest&#xA;through the trees when ironing out a workflow - generally to find out I way&#xA;over complicated the solution OR worse, started solving a problem I don&#39;t even&#xA;have.&#xA;&#xA;## First Attempt: Local Progress Tracker&#xA;&#xA;Well that&#39;s where I&#39;ve been for a few weeks... I&#39;m building Nexus, my&#xA;second-brain at work to collaborate with agents on the truckload of stuff I&#39;m&#xA;expected to get done. For a while now I&#39;ve had a &#34;working-notes&#34; repo, which is&#xA;basically a blog, built with markata and navigated via markdown-lsp, where I do&#xA;like what I do here - take daily notes, track projects and status, and it gets&#xA;built into a nice little website I can reference with my boss.&#xA;&#xA;Now that we have copilot in full-swing, I&#39;m trying to integrate agents a bit&#xA;more. Opencode has made this so nice - so many tools and modes of interaction,&#xA;highly customizable interface but also an amazing default experience... So I&#xA;was trying to lean into using agents and subagents for more work I started down&#xA;the path of building out a progress tracker. I started with a simple &#34;skill&#34;&#xA;that told the agent to put some info into a sqlite file, and even create the&#xA;file and schema based on the work. This worked fine, but was specific to each&#xA;repo (and actually each worktree I was in) and it was hard for me to get&#xA;visibility into all the work my fleet of agents was doing. Now that&#39;s actually&#xA;problem 1 - I don&#39;t have a fleet of agents, I had some terminal sessions going&#xA;with opencode, but I got it in my head that I was going to have an army of&#xA;Claude&#39;s on my computer, constantly and autonomously knocking out tickets and I&#xA;needed to know who was doing what, where, when, and why..&#xA;&#xA;## Nexus V1 &amp; V2: The Over-Engineering Phase&#xA;&#xA;So, I dropped the local &#34;progress tracker&#34; and jumped into a huge FastAPI&#xA;project that I called Nexus. It was a python cli + api, with a server for&#xA;centralized management. It presented a kanban board, had policy gates on&#xA;&#34;plans&#34; being approved before work could start on an Epic (and therefore any&#xA;child tickets). It has worktree tracking and automation, etc. It had a lot...&#xA;it didn&#39;t all work, and it was hard to build the autonomous system... I wanted&#xA;agentic feedback loops where `voidshaper` and I made epic plans for Epics (see the pun?) and then once the Plan was approved `star-commander` comes on the scene and makes tickets or checks tickets, depending on what&#39;s already ready to go it farmed out the work to `starsmith` (and variants for complexity) to build and then automatically calls in `recon-officer` and `qa-engineer` and at the end of it `gatekeeper` came in and&#xA;approved or denied the changes. If denied - automatically start the loop again,&#xA;tracking the work in Nexus, if approved - rebase and merge the branch, clean up&#xA;the worktree, update the ticket, close it, and get working on the next thing&#xA;that opens up. Ticket dependencies were in there, tracking stale agent&#xA;sessions, clever routing of tasks to smaller models where appropriate.... you&#xA;can see that I went too far too fast too hard.&#xA;&#xA;![20260203124603_d5948740.png](https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20260203124603_d5948740.png)&#xA;&#xA;Nexus went through 2 or 3 iterations of this feature set. I was building it with several constraints in mind - specifically at work. 1. rate-limiting on large models (so not just using opus for everything), 2. good stewardship (not burning down cities for docstrings - farm out that work to haiku or a -mini model), 3. Copilot support - even though I like to use opencode, I wanted to supper copilot cli and in vscode as a means to share this with my coworkers who were mostly using vscode, 4. agent sessions were dying so I needed some kind of liveness probe for manual intervention in sessions where maybe the vpn died and the agent lost network... stuff like this was on my mind - but you know what wasn&#39;t? actually doing some work... I was solving problems I don&#39;t have, but were fun to think about.&#xA;&#xA;## The Reality Check&#xA;&#xA;So, what are my problems? I boiled them down to a few things...&#xA;&#xA;1. I want to manage my workstreams in workspaces - folders on my computer where I put git worktrees&#xA;2. I want varying levels of ai automation in my workflows... some things could be handled by an agent fully autonmously, but most things I&#39;m at least paired up, reviewing diffs still, doing research while working, etc.&#xA;3. In those varying levels of automation, I wanted the same amount of task tracking to a centralized location&#xA;&#xA;And after 2 weeks of ADHD-driven hyper focus, and many iterations on Nexus,&#xA;then Nexus V2.... what happened is that Nexus V2 died, and we say long live&#xA;Nexus V3!&#xA;&#xA;## Nexus V3: The Pragmatic Pivot&#xA;&#xA;Nexus V3 is the same idea, but different approach... I&#39;m leaning into opencode&#xA;tooling specifically, dropping my care to support copilot given the lack of&#xA;features. I&#39;m using a few opencode [plugins](https://opencode.ai/docs/plugins/)&#xA;([opencode-notify](https://github.com/kdcokenny/opencode-notify) and&#xA;[opencode-background-agents](https://github.com/kdcokenny/opencode-background-agents)&#xA;and a few [commands](https://opencode.ai/docs/commands/). Instead of building&#xA;my own tracker, I&#39;m using [kanboard](https://kanboard.org/) because it&#39;s&#xA;basically a feature-complete agile/sprint/kanban board that I use at home, has&#xA;a simple plugin ecosystem for light customization, and solves practically every&#xA;status-tracking problem I tried to build from the ground up initially - ticket&#xA;dependencies/linkages, actions to change ticket colors for a simple intuitive&#xA;UI based on state, easy columns and tagging configuration, a simple API and&#xA;there&#39;s even an [mcp server](https://github.com/bivex/kanboard-mcp).&#xA;&#xA;So, I&#39;ve given up on the full automation for now, although&#xA;[opencode-pilot](https://github.com/athal7/opencode-pilot) looks VERY PROMISING&#xA;for this in the future. Today though, through some simple commands to give to&#xA;agents for updating kanboard, I manually put them in worktrees, and they get to&#xA;work - the tracking and human-in-the-loop model is going well for the work I&#xA;need done.&#xA;&#xA;## Lessons Learned&#xA;&#xA;I learned and relearned plenty of lessons on this over the last 2 weeks... Data&#xA;models matter more than almost anything, well-defined workflows are required if&#xA;you want agents to help you iterate, and not everything has to be a product...&#xA;That last one&#39;s personal, but every time I have an idea I **think** is good,&#xA;I&#39;m sure it&#39;ll be something to share, but a good lesson for me is to just build&#xA;the things I need for me, and **eventually** maybe it can be cleaned up to&#xA;share, but when I start building something with anyone other than **me** in&#xA;mind, I&#39;m in for a long hard journey&#xA;&#xA;## Current State &amp; Future&#xA;&#xA;So what&#39;s the summary? I don&#39;t think I know how to agent super well yet - but&#xA;I&#39;m trying to get better to stay on the forefront of my co-workers who I see&#xA;using AI in simple and sometimes scary ways&#xA;&#xA;!!! danger &#34;Copilot x sudo&#34;&#xA;&#xA;    Do not give copilot `sudo` on your CI server and say &#34;fix my problem&#34;... are you retarded???&#xA;&#xA;I am not going hardcore with [ralph&#xA;wiggum](https://awesomeclaude.ai/ralph-wiggum) or&#xA;[gastown](https://github.com/steveyegge/gastown) - although those inspired&#xA;Nexus v1 and v2, but I am dialing in my agentic workflow with some simple&#xA;specialized agents, farming out work to subagents for context management,&#xA;planning ahead of time to put appropriate context in a ticket, and getting&#xA;close to having agents check out tickets, make worktrees, and do simple work by&#xA;themselves (this was working in Nexus V2 but only intermittenly).&#xA;&#xA;Someday I&#39;ll open-source Nexus and share the configuration and workflow, for&#xA;now it&#39;s private as I&#39;m actually using it to build out what I want rather than&#xA;trying to recreate gastown with a cool space theme.&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>New Job - Caterpillar Autonomy</title>
    <id>https://pype.dev/new-job-caterpillar-autonomy/</id>
    <updated>2026-01-26T10:24:54Z</updated>
    <published>2026-01-26T10:24:54Z</published>
    <link href="https://pype.dev/new-job-caterpillar-autonomy/" rel="alternate" type="text/html"></link>
    <summary type="text">In im-back-from-the-dead I mentioned my new role that started this year - it&#39;s a return to Caterpillar Autonomy. I built some data pipelines and junior-grade...</summary>
    <content type="text">&#xA;In [[im-back-from-the-dead]] I mentioned my new role that started this year -&#xA;it&#39;s a return to Caterpillar Autonomy. I built some data pipelines and&#xA;junior-grade infrastructure 5 years ago but left over burn-out at the prospect of&#xA;a job with smaller scoped work and more technical guidance. That was a good&#xA;move, and in God&#39;s sovereignty he&#39;s brought me back. Now I&#39;m looking at code,&#xA;thankfully not that I wrote, but that the guy after me wrote - it accomplished&#xA;a job, like my original work did, but also like what I built back then -&#xA;there&#39;s better ways today. The amount of things in front of me is absolutely&#xA;daunting, and the people on the team have been seeded with a very high opinion&#xA;of me... I don&#39;t know how much is valid and how much is hype, but I&#39;m gonna try&#xA;to live up to it.&#xA;&#xA;One way I&#39;m striving to do that is to maximize my efficiency with the AI coding&#xA;tools available to me. We have Github Copilot and I&#39;ve picked up a lot over the&#xA;course of the last few years (and especially more recently) in using agents,&#xA;planning out work, documenting plans for agents to follow, splitting up work&#xA;via worktrees, etc. I feel pretty good about where I&#39;m going and someday I&#xA;might even release Nexus. Nexus is serving as my second-brain at work, the hub&#xA;where I collaborate with my fleet of agents on the work that must get done.&#xA;Details to come on this, but the thing that matters is that in ironing out&#xA;workflow I&#39;ve moved from prompt + chat to really managing a long-lived stream&#xA;of work. AI has been changing the world, and there&#39;s been developer hype for&#xA;years now. But &#34;make me a cool app, no mistakes&#34; isn&#39;t going to cut it. Even&#xA;&#34;make an app but generate a plan first&#34; isn&#39;t going to cut it... Developers&#xA;have to adopt a higher level role, a systems-oriented and architecture-driven&#xA;worldview must become primary in order to keep up. Code-gen and syntax writing&#xA;are not what developers were **ever** paid to do, although many believed so.&#xA;Our jobs have been to solve problems and deliver code that solves the problem.&#xA;The code is cheap now, but solving problems still is a human task.&#xA;&#xA;In the Autonomy group - there&#39;s problems all up and down the stack. My focus is&#xA;on infrastructure and developer operations - it&#39;s become my bread and butter&#xA;over the last several years. I&#39;m excited to help the team grow, and I&#39;m excited&#xA;to grow personally/technically as I lean into the agentic workflow to produce&#xA;code that I&#39;m actually proud of, that has my name on the commit, and that&#xA;solves real problems.&#xA;&#xA;## Example - Local Development&#xA;&#xA;One of the first things I&#39;m tackling is a developer-pain-point of working on&#xA;their laptop. I&#39;ve been in this space for years, mostly with python programmer&#xA;who are writing data science code. They don&#39;t know about virtual environments,&#xA;checking $PATH, assuming bad state in their terminal session, how to configure&#xA;VS Code, etc. Often they just want to write some scripts and somehow test it.&#xA;The solution I see most often is for devs to write code in JupyterLab/Notebooks&#xA;in AWS or some environment close to their data - this is fine I guess, but it&#39;s&#xA;not developing good pipelines, and it&#39;s tedious as hell. In my last job I&#xA;helped set developers up with workflows that allowed them to run their IDE of&#xA;choice locally (getting all the goodies of syntax highlighting, LSP, etc) and a&#xA;CLI that took their code and ran it in the cloud, right next to data, in the&#xA;same way that prod runs. It was a hit. After that I introduced some tools to&#xA;help them manage python environments - we had strict templating requirements in&#xA;our projects, so making tools to automate those things wasn&#39;t too hard - it&#39;s&#xA;much easier than trying to make something flexible for every use case. The&#xA;opinions made the automation and tooling easy to make and distribute.&#xA;&#xA;Well I&#39;m up against a similar task now, but oh so much worse... Larger team,&#xA;larger environment sprawl, larger infrastructure mismanagement, the whole&#xA;gambit. And I&#39;m here for it... Here&#39;s the first problem I&#39;m addressing - local&#xA;development for Airflow DAGs that run in an Airflow deployment on Kubernetes.&#xA;The deployment itself is a little odd, Airflow is an orchestrator, all the&#xA;pipelines run in external AWS Batch jobs - so a DAG hits the Batch API to run&#xA;the code. The design there is actually nice, but how are devs testing code?&#xA;&#xA;Oh that&#39;s easy... they SSH into the prod server, which is a 5 year old desktop&#xA;THAT I BUILT WITH A CO-WORKER BEFORE I WAS IN AUTONOMY THE FIRST TIME... hold&#xA;on, WHAT!? Yes, it&#39;s true.. so they SSH into the prod server, run some bash&#xA;scripts in their userspace that setup airflow and a few db utilities in a&#xA;docker compose stack, authenticate with AWS themselves from that server, and&#xA;then they run DAGs against real data to test it... I am beyond shook.&#xA;&#xA;Here&#39;s what I&#39;ve put together - a bootstrap process (I like `just` + PEP 723&#xA;python scripts as opposed to bash, but to each their own, and bash of course&#xA;has its place) that spins up a [kind](https://kind.sigs.k8s.io/) cluster on&#xA;their laptop, the process pulls some private images and loads them into the&#xA;kind cluster, it installs airflow from a helm chart (the same helm chart we&#39;ll&#xA;use in dev and prod... no more docker compose over here, kubectl over there),&#xA;and everything just. comes. up. No SSH into ancient server, no touching cloud&#xA;infra (they get MinIO and a DB container to emulate S3 and RDS in our AWS&#xA;accounts), no sweat on testing DAGs. They stage some data in MinIO (`just open&#xA;minio` handles the port-forward and opens the browser), then `just open&#xA;airflow` (their DAGs are hot-reloaded via hostPath mounting), and they can run&#xA;DAGs locally until they&#39;re satisfied with the results.&#xA;&#xA;It&#39;s taken me about a week of split-focused effort (I mentioned Nexus and I&#39;ve&#xA;been co-building and dogfooding that at the same time) but I&#39;m proud of that&#xA;local setup now. I am a bit shocked they&#39;ve dealt with a brittle, hacky, often&#xA;broken development workflow for the last 4 years or so, but that development I&#xA;suppose.&#xA;&#xA;## The Point&#xA;&#xA;This post wasn&#39;t meant to be me glazing myself for awesome local development&#xA;practices, I am simply excited about this new chapter. I love solving problems,&#xA;and I love owning those solutions. There&#39;s a whole mess of things to address,&#xA;my mind is buzzing, and I feel like God has blessed me with renewed passion&#xA;(again see [[im-back-from-the-dead]]). I&#39;ve given up some pay and some freedom&#xA;to take this role, but I think it&#39;ll pay dividends.&#xA;&#xA;Life happens to all of us - this role change affected a lot for me, it&#39;s been&#xA;hard to digest some of those changes, but the work is good, the development is&#xA;fun, the new world of using agents to fly through things you&#39;re fluent in is&#xA;exciting, and I&#39;m here to help a team that desperately needs it to improve&#xA;their lives and the work we do for Cat Autonomy.&#xA;&#xA;I&#39;m still pissed at Caterpillar Executives for RTO ruining parts of my life,&#xA;but in God&#39;s sovereignty their idiocy has led to non-trivial blessing, so I can&#xA;say &#34;Praise the Lord&#34;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Increase inotify limit in your CI workers</title>
    <id>https://pype.dev/increase-inotify-limit-in-your-ci-workers/</id>
    <updated>2025-12-30T06:11:49Z</updated>
    <published>2025-12-30T06:11:49Z</published>
    <link href="https://pype.dev/increase-inotify-limit-in-your-ci-workers/" rel="alternate" type="text/html"></link>
    <summary type="text">Today I tripped over a CI failure that I had to think about for a while.</summary>
    <content type="html">&lt;p&gt;Today I tripped over a CI failure that I had to think about for a while.&lt;/p&gt;&#xA;&lt;p&gt;I build &lt;a href=&#34;https://github.com/zensical/zensical&#34;&gt;zensical&lt;/a&gt; static sites in CI on&#xA;my Forgejo instance. These builds had been working fine, then suddenly started&#xA;failing with no code changes. Naturally, I assumed something upstream broke —&#xA;maybe a new uv release, maybe zensical.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I pinned versions.&lt;/li&gt;&#xA;&lt;li&gt;I tested older versions.&lt;/li&gt;&#xA;&lt;li&gt;Same failure every time.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;That ruled out regressions and pushed me toward the environment.&lt;/p&gt;&#xA;&lt;p&gt;I pulled the runner and worker images locally and built the sites just fine&amp;hellip;&#xA;But that doesn&amp;rsquo;t perfectly emulate the CI setup - my forgejo runner relies on&#xA;docker-in-docker and so we aren&amp;rsquo;t &lt;strong&gt;just&lt;/strong&gt; running a container on a host, we have&#xA;this middle layer to consider&amp;hellip; I wasn&amp;rsquo;t sure how to really test this out&#xA;locally so I succomed to AI and here&amp;rsquo;s where Jipity got me in about 5&#xA;minutes&amp;hellip;&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-failure&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The failure&lt;/span&gt; &lt;a href=&#34;#the-failure&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;The builds blew up with:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;thread &#39;zrx/monitor&#39; panicked at .../zensical-watch/src/agent/monitor.rs:154:49:&#xA;called `Result::unwrap()` on an `Err` value:&#xA;Error { kind: Io(Os { code: 24, message: &amp;quot;Too many open files&amp;quot; }) }&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;At first glance it means nothing to me but Jipity says this screams ulimit.&lt;/p&gt;&#xA;&lt;p&gt;So following the AI overlords I checked:&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;ulimit -n&lt;/code&gt; was already very high&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;/proc/sys/fs/inotify/max_user_watches&lt;/code&gt; was also very high&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;PID limits&lt;/code&gt; were not constrained&lt;/p&gt;&#xA;&lt;p&gt;Everything looked fine according to Jipity.&lt;/p&gt;&#xA;&lt;p&gt;Yet the panic persisted.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-real-culprit&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The real culprit&lt;/span&gt; &lt;a href=&#34;#the-real-culprit&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;The actual limit being hit was:&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;/proc/sys/fs/inotify/max_user_instances&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;In my Forgejo runner container, it was set to 128.&lt;/p&gt;&#xA;&lt;p&gt;That turns out to be far too low for zensical.&lt;/p&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s what ChatGPT said:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Even during a normal zensical build, the tool spins up its watch subsystem,&#xA;which creates many inotify instances. Once it crosses the kernel limit,&#xA;inotify_init() fails with EMFILE, and the process panics because the error is&#xA;unwrapped.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h2 id=&#34;the-fix&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The fix&lt;/span&gt; &lt;a href=&#34;#the-fix&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Raising the inotify instance limit fixed it immediately:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;echo 1024 &amp;gt; /proc/sys/fs/inotify/max_user_instances&#xA;RUST_BACKTRACE=full uvx zensical build --clean&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;After that, the build succeeded consistently.&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Prettier Docker ‘ps’ Command</title>
    <id>https://pype.dev/prettier-docker-ps-command/</id>
    <updated>2025-12-29T05:33:05Z</updated>
    <published>2025-12-29T05:33:05Z</published>
    <link href="https://pype.dev/prettier-docker-ps-command/" rel="alternate" type="text/html"></link>
    <summary type="text">The command is very useful, but I hate reading the output. Turns out, you can make it prettier:</summary>
    <content type="html">&lt;p&gt;The &lt;code&gt;docker ps&lt;/code&gt; command is very useful, but I hate reading the output. Turns&#xA;out, you can make it prettier:&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;docker ps&lt;/code&gt;&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ndash;format &amp;ldquo;table&amp;rdquo; is implied with the command.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;pre&gt;&lt;code&gt;&#xA;❯ docker ps --format &amp;quot;table&amp;quot; | grep can&#xA;9b716a7d1ab0   postgres:17                                               &amp;quot;docker-entrypoint.s…&amp;quot;   13 hours ago    Up 13 hours (healthy)            0.0.0.0:5432-&amp;gt;5432/tcp, [::]:5432-&amp;gt;5432/tcp                                                cannalyzer-db-1&#xA;f7708ea0c112   adminer                                                   &amp;quot;entrypoint.sh docke…&amp;quot;   13 hours ago    Up 13 hours                      0.0.0.0:8081-&amp;gt;8080/tcp, [::]:8081-&amp;gt;8080/tcp                                                cannalyzer-adminer-1&#xA;93cd67719ed4   frontend:latest                                           &amp;quot;/docker-entrypoint.…&amp;quot;   13 hours ago    Up 13 hours                      0.0.0.0:5173-&amp;gt;80/tcp, [::]:5173-&amp;gt;80/tcp                                                    cannalyzer-frontend-1&#xA;f517625fca98   traefik:3.0                                               &amp;quot;/entrypoint.sh --pr…&amp;quot;   13 hours ago    Up 13 hours                      0.0.0.0:80-&amp;gt;80/tcp, [::]:80-&amp;gt;80/tcp, 0.0.0.0:8090-&amp;gt;8080/tcp, [::]:8090-&amp;gt;8080/tcp           cannalyzer-proxy-1&#xA;f4daa036216e   schickling/mailcatcher                                    &amp;quot;sh -c &#39;mailcatcher …&amp;quot;   13 hours ago    Up 13 hours                      0.0.0.0:1025-&amp;gt;1025/tcp, [::]:1025-&amp;gt;1025/tcp, 0.0.0.0:1080-&amp;gt;1080/tcp, [::]:1080-&amp;gt;1080/tcp   cannalyzer-mailcatcher-1&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;But you can pass a template string to the &lt;code&gt;--format&lt;/code&gt; option, like so:&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;docker ps --format &amp;quot;table {{.Names}}&amp;quot;&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;&#xA;✗ docker ps --format &amp;quot;table {{.Names}}&amp;quot; | grep can&#xA;cannalyzer-db-1&#xA;cannalyzer-adminer-1&#xA;cannalyzer-frontend-1&#xA;cannalyzer-proxy-1&#xA;cannalyzer-mailcatcher-1&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;code&gt;docker ps --format &amp;quot;table {{.Names}}\t{{.Status}}\t{{.Ports}}&amp;quot;&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;&#xA;❯ docker ps --format &amp;quot;table {{.Names}}\t{{.Ports}}&amp;quot; | grep can&#xA;cannalyzer-db-1             0.0.0.0:5432-&amp;gt;5432/tcp, [::]:5432-&amp;gt;5432/tcp&#xA;cannalyzer-adminer-1        0.0.0.0:8081-&amp;gt;8080/tcp, [::]:8081-&amp;gt;8080/tcp&#xA;cannalyzer-frontend-1       0.0.0.0:5173-&amp;gt;80/tcp, [::]:5173-&amp;gt;80/tcp&#xA;cannalyzer-proxy-1          0.0.0.0:80-&amp;gt;80/tcp, [::]:80-&amp;gt;80/tcp, 0.0.0.0:8090-&amp;gt;8080/tcp, [::]:8090-&amp;gt;8080/tcp&#xA;cannalyzer-mailcatcher-1    0.0.0.0:1025-&amp;gt;1025/tcp, [::]:1025-&amp;gt;1025/tcp, 0.0.0.0:1080-&amp;gt;1080/tcp, [::]:1080-&amp;gt;1080/tcp&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 id=&#34;picture&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Picture&lt;/span&gt; &lt;a href=&#34;#picture&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I noticed my template isn&amp;rsquo;t folding the codeblocks in a way that actually makes this post look like I&amp;rsquo;m lying!&lt;/p&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20251229122717_67e76a67.png&#34; alt=&#34;20251229122717_67e76a67.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Setup A Cloudflare Tunnel With Terraform</title>
    <id>https://pype.dev/setup-a-cloudflare-tunnel-with-terraform/</id>
    <updated>2025-12-12T21:06:59Z</updated>
    <published>2025-12-12T21:06:59Z</published>
    <link href="https://pype.dev/setup-a-cloudflare-tunnel-with-terraform/" rel="alternate" type="text/html"></link>
    <summary type="text">I am cooking up some stuff at home and want to put it on the interwebs, but I don&#39;t want it on the same infra as my homelab. Now... I only have a server or...</summary>
    <content type="html">&lt;p&gt;I am cooking up some stuff at home and want to put it on the interwebs, but I&#xA;don&amp;rsquo;t want it on the same infra as my homelab. Now&amp;hellip; I only have a server or&#xA;2, so to some degree it will be, but networking-wise I didn&amp;rsquo;t want to funnel&#xA;extra traffic through my reverse proxy.&lt;/p&gt;&#xA;&lt;p&gt;So, I&amp;rsquo;d heard about Cloudflare Tunnels - they sound like P2P VPN to me, but I&#xA;know there&amp;rsquo;s layers of the networking stack I&amp;rsquo;m blatantly ignoring. &amp;ldquo;What the&#xA;tunnel is&amp;rdquo; isn&amp;rsquo;t much the point - I&amp;rsquo;m here to show you how to set one up and&#xA;get yourself a fancy &lt;a href=&#34;https://app.mydomain.com&#34;&gt;https://app.mydomain.com&lt;/a&gt; for your web app running&#xA;kind of wherever you want&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Example Repo linked at the bottom&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h2 id=&#34;requirements&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Requirements&lt;/span&gt; &lt;a href=&#34;#requirements&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;ol start=&#34;0&#34;&gt;&#xA;&lt;li&gt;Terraform or open-tofu. I currently use open-tofu but either would be fine.&#xA;&lt;code&gt;brew install open-tofu&lt;/code&gt; is a simple way to get going&lt;/li&gt;&#xA;&lt;li&gt;Cloudflare account with a domain&lt;/li&gt;&#xA;&lt;li&gt;API token with permissions:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;Account:Cloudflare Tunnel:Edit&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Zone:DNS:Edit&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;cloudflared&lt;/code&gt; (the example repo runs cloudflared in a docker compose stack)&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;tunnel&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Tunnel&lt;/span&gt; &lt;a href=&#34;#tunnel&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;The module is simple and has just a few resources:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ tofu state list&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;module.tunnel.cloudflare_record.tunnel&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;module.tunnel.cloudflare_tunnel_config.this&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;module.tunnel.cloudflare_zero_trust_tunnel_cloudflared.this&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;module.tunnel.random_id.tunnel_secret&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We see there will be the a DNS record that tofu references by the key &amp;ldquo;tunnel&amp;rdquo;.&#xA;There is a tunnel configuration resource, the tunnel resource itself, and&#xA;finally the associated secret required for the cloudflared daemon that will run&#xA;alongside your webapp.&lt;/p&gt;&#xA;&lt;p&gt;To get started you&amp;rsquo;ll need to fill out the example &lt;code&gt;terraform.tfvars&lt;/code&gt; file with&#xA;your info:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Copy to terraform.tfvars and fill in values&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# DO NOT commit terraform.tfvars to git&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;cloudflare_api_token&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;your-api-token-here&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;cloudflare_account_id&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;your-account-id&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;cloudflare_zone_id&lt;/span&gt;    &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;your-zone-id&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;domain&lt;/span&gt;                &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;example.com&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;subdomain&lt;/span&gt;             &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;app&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;tunnel_name&lt;/span&gt;           &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;my-tunnel&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;origin_service&lt;/span&gt;        &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;http://localhost:8000&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can grab your account id and zone id from Cloudflare&amp;rsquo;s dashboard for your&#xA;domain. It&amp;rsquo;s near the bottom of the Overview page&lt;/p&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20251213113332_0e0f09b8.png&#34; alt=&#34;20251213113332_0e0f09b8.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;Then I presume you have a domain already, but if not hop over to namecheap to&#xA;snag one and then register it with cloudflare so they can manage your DNS. I&#xA;have terraform for this as well, a future blog post will combine this with a&#xA;fuller terraform&amp;rsquo;d cloudflare setup for simple domain use cases&lt;/p&gt;&#xA;&lt;p&gt;Once you fill those out, hit it with the &lt;code&gt;tofu init&lt;/code&gt; and &lt;code&gt;tofu plan&lt;/code&gt; to see what&amp;rsquo;s up&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;NOTE: &lt;code&gt;terraform.tfvars&lt;/code&gt; is automatically sourced by terraform/tofu, you can name the file differently and then pass &lt;code&gt;-var-file=myvars.tfvars&lt;/code&gt; to the commands&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;The initial plan should look something like this:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;OpenTofu used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  + create&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;OpenTofu will perform the following actions:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;# module.tunnel.cloudflare_record.tunnel will be created&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  + resource &lt;span class=&#34;s2&#34;&gt;&amp;#34;cloudflare_record&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;tunnel&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;allow_overwrite&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;false&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;comment&lt;/span&gt;         &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Managed by Terraform - soonish-tunnel&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;content&lt;/span&gt;         &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;known after apply&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;created_on&lt;/span&gt;      &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;known after apply&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;hostname&lt;/span&gt;        &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;known after apply&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;id&lt;/span&gt;              &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;known after apply&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;metadata&lt;/span&gt;        &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;known after apply&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;modified_on&lt;/span&gt;     &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;known after apply&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;name&lt;/span&gt;            &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;app&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;proxiable&lt;/span&gt;       &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;known after apply&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;proxied&lt;/span&gt;         &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;true&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;ttl&lt;/span&gt;             &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;known after apply&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;            &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;CNAME&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;value&lt;/span&gt;           &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;known after apply&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;zone_id&lt;/span&gt;         &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;lt;REDACTED&amp;gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;# module.tunnel.cloudflare_tunnel_config.this will be created&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  + resource &lt;span class=&#34;s2&#34;&gt;&amp;#34;cloudflare_tunnel_config&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;this&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;account_id&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;lt;REDACTED&amp;gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;id&lt;/span&gt;         &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;known after apply&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;tunnel_id&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;known after apply&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + config &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          + ingress_rule &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              + &lt;span class=&#34;nv&#34;&gt;hostname&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;app.notifiq.net&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              + &lt;span class=&#34;nv&#34;&gt;service&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;http://localhost:8000&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          + ingress_rule &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              + &lt;span class=&#34;nv&#34;&gt;service&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;http_status:404&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;# module.tunnel.cloudflare_zero_trust_tunnel_cloudflared.this will be created&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  + resource &lt;span class=&#34;s2&#34;&gt;&amp;#34;cloudflare_zero_trust_tunnel_cloudflared&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;this&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;account_id&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;lt;REDACTED&amp;gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;cname&lt;/span&gt;        &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;known after apply&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;id&lt;/span&gt;           &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;known after apply&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;name&lt;/span&gt;         &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;soonish-tunnel&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;secret&lt;/span&gt;       &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;sensitive value&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;tunnel_token&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;sensitive value&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;# module.tunnel.random_id.tunnel_secret will be created&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  + resource &lt;span class=&#34;s2&#34;&gt;&amp;#34;random_id&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;tunnel_secret&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;b64_std&lt;/span&gt;     &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;known after apply&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;b64_url&lt;/span&gt;     &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;known after apply&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;byte_length&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;32&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;dec&lt;/span&gt;         &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;known after apply&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;hex&lt;/span&gt;         &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;known after apply&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      + &lt;span class=&#34;nv&#34;&gt;id&lt;/span&gt;          &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;known after apply&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Plan: &lt;span class=&#34;m&#34;&gt;4&lt;/span&gt; to add, &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; to change, &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; to destroy.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;As long as that looks good you to, then we &lt;code&gt;tofu apply&lt;/code&gt; next (type &lt;code&gt;yes&lt;/code&gt; when&#xA;asked or pass &lt;code&gt;-auto-approve&lt;/code&gt;)&lt;/p&gt;&#xA;&lt;p&gt;Afterwards &lt;code&gt;tofu state list&lt;/code&gt; should show you the 4 resources, and if you go to&#xA;your cloudflare zone&amp;rsquo;s dashboard you should see the CNAME associated with the&#xA;tunnel address&lt;/p&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20251213120004_d199e5fd.png&#34; alt=&#34;20251213120004_d199e5fd.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;h2 id=&#34;daemon&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Daemon&lt;/span&gt; &lt;a href=&#34;#daemon&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Run the compose stack or the binary itself. Get the token from terraform state with &lt;code&gt;tofu output -raw tunnel_token&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;TUNNEL_TOKEN=$(tofu output -raw tunnel_token) docker compose up -d&lt;/code&gt; will do you nicely&lt;/p&gt;&#xA;&lt;p&gt;Enjoy your tunnel!&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/pypeaday/example-terraform-cloudflare-tunnel&#34;&gt;example repo&lt;/a&gt;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>COLUMNS Env Var For Nicer Screenshots</title>
    <id>https://pype.dev/columns-env-var-for-nicer-screenshots/</id>
    <updated>2025-12-08T05:16:55Z</updated>
    <published>2025-12-08T05:16:55Z</published>
    <link href="https://pype.dev/columns-env-var-for-nicer-screenshots/" rel="alternate" type="text/html"></link>
    <summary type="text">I was working on uv-run-pep-723-is-a-match-made-in-heaven and I wanted to grab a screenshot of a TUI, but my terminal is full screen and the TUI was then...</summary>
    <content type="text">&#xA;I was working on [[uv-run-pep-723-is-a-match-made-in-heaven]] and I wanted to grab a screenshot of a TUI, but my terminal is full screen and the TUI was then super stretched... Nice for working and using it, but not nice for a screenshot going into a blog post... see the difference `export COLUMNS=120` does here!&#xA;&#xA;```&#xA;COLUMNS=120 mytui.py&#xA;```&#xA;&#xA;![20251208111709_aa06bd03.png](https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20251208111709_aa06bd03.png)&#xA;&#xA;```&#xA;mytui.py&#xA;```&#xA;&#xA;![20251208111820_a209638f.png](https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20251208111820_a209638f.png)&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>UV Run + PEP 723 Is A Match Made In Heaven</title>
    <id>https://pype.dev/uv-run-pep-723-is-a-match-made-in-heaven/</id>
    <updated>2025-12-08T04:59:10Z</updated>
    <published>2025-12-08T04:59:10Z</published>
    <link href="https://pype.dev/uv-run-pep-723-is-a-match-made-in-heaven/" rel="alternate" type="text/html"></link>
    <summary type="text">This post will be short but hopefully be a dense few paragraphs about how using along with PEP 723 is life-changing.</summary>
    <content type="text">&#xA;This post will be short but hopefully be a dense few paragraphs about how using&#xA;`uv run foo.py` along with [PEP 723](https://peps.python.org/pep-0723/) is&#xA;life-changing.&#xA;&#xA;## PEP 723&#xA;&#xA;Python Enhancement Proposals (PEP) are the community&#39;s way of improving the&#xA;python language and ecosystem and PEP 723 is one of my favorites. It permits&#xA;adding python metadata right to your script which allows `python` to setup the&#xA;script&#39;s dependencies at runtime.&#xA;&#xA;## UV&#xA;&#xA;[[uv]] makes it even better with it&#39;s super fast resolution and environment&#xA;setup. I don&#39;t have any posts about uv yet, but here&#39;s the&#xA;[docs](https://docs.astral.sh/uv/getting-started/installation/), installing&#xA;`uv` is now apart of my dev-machine setup because I need it everywhere!&#xA;&#xA;## The Magic&#xA;&#xA;I&#39;m experiencing the power of `uv run myscript.py` as I&#39;ve integrated a python&#xA;script into my tmux workflow for managing sessions as well as groups of&#xA;git-worktrees to keep development-ideas contained, easy to find, and easy to&#xA;manage.&#xA;&#xA;!!! warning &#34;The Series&#34;&#xA;&#xA;    This post is in my &#34;If You Want It Make It So&#34; series because of the workspaces thing generally, not the dbztui example below, but for me - having &#39;uv run&#39; as a pretty powerful Bash replacement makes my development workflow easier to build on and manage&#xA;&#xA;My [workspaces docs](https://pypeaday.github.io/dotfiles/terminal/workspaces/)&#xA;explain the setup a bit, and that script is in my&#xA;[dotfiles](https://github.com/pypeaday/dotfiles/blob/main/workspaces/.local/bin/ws.py)&#xA;&#xA;For a shorter example, here&#39;s an example that has regular `pip` style&#xA;dependencies, a `git+https` dependency, and is a tui - not just a top to bottom&#xA;script&#xA;&#xA;!!! note &#34;What is it?&#34;&#xA;&#xA;    This is my DBZTUI script - it uses a beta package from Waylon called&#xA;    ninesui and calls the dragonball-api to give you a handy way to explore the&#xA;    Dragon Ball Universe from the glorious comfort of your terminal&#xA;&#xA;Copy this code into `dbztui.py`&#xA;&#xA;!!! note &#34;Execution&#34;&#xA;&#xA;    You can `chmod +x` this script with the shebang to tell your shell to use uv to run it or just `uv run dbztui.py` will also work just fine&#xA;&#xA;```python&#xA;#!/usr/bin/env -S uv run --quiet --script&#xA;# /// script&#xA;# requires-python = &#34;&gt;=3.10&#34;&#xA;# dependencies = [&#xA;#     &#34;ninesui @ git+https://github.com/waylonwalker/ninesui.git&#34;,&#xA;#     &#34;httpx&#34;,&#xA;#     &#34;deep-translator&#34;,&#xA;# ]&#xA;# ///&#xA;from typing import Optional, List, TypeVar, ClassVar, Any, Dict&#xA;from pydantic import BaseModel, Field, HttpUrl&#xA;import httpx&#xA;from textual import log&#xA;from ninesui import CommandSet, Command, NinesUI&#xA;from functools import lru_cache&#xA;from deep_translator import GoogleTranslator&#xA;import json&#xA;import os&#xA;&#xA;BASE_URL = &#34;https://dragonball-api.com/api/&#34;&#xA;&#xA;# Translation cache file&#xA;CACHE_DIR = os.path.expanduser(&#34;~/.cache/dbztui&#34;)&#xA;CACHE_FILE = os.path.join(CACHE_DIR, &#34;translation_cache.json&#34;)&#xA;&#xA;# Create cache directory if it doesn&#39;t exist&#xA;os.makedirs(CACHE_DIR, exist_ok=True)&#xA;&#xA;# Load translation cache from file&#xA;translation_cache: Dict[str, str] = {}&#xA;if os.path.exists(CACHE_FILE):&#xA;    try:&#xA;        with open(CACHE_FILE, &#34;r&#34;, encoding=&#34;utf-8&#34;) as f:&#xA;            translation_cache = json.load(f)&#xA;    except Exception as e:&#xA;        log(f&#34;Error loading translation cache: {e}&#34;)&#xA;&#xA;# Initialize translator&#xA;translator = GoogleTranslator(source=&#39;es&#39;, target=&#39;en&#39;)&#xA;&#xA;T = TypeVar(&#34;T&#34;, bound=&#34;DBZResource&#34;)&#xA;&#xA;@lru_cache(maxsize=1000)&#xA;def translate_text(text: str) -&gt; str:&#xA;    &#34;&#34;&#34;Translate text from Spanish to English with caching&#34;&#34;&#34;&#xA;    if not text or len(text) &lt; 5:  # Don&#39;t translate very short texts&#xA;        return text&#xA;&#xA;    # Check if translation is in cache&#xA;    if text in translation_cache:&#xA;        return translation_cache[text]&#xA;&#xA;    try:&#xA;        # Translate text&#xA;        translated = translator.translate(text)&#xA;&#xA;        # Save to cache&#xA;        translation_cache[text] = translated&#xA;&#xA;        # Periodically save cache to file&#xA;        if len(translation_cache) % 10 == 0:  # Save every 10 new translations&#xA;            try:&#xA;                with open(CACHE_FILE, &#34;w&#34;, encoding=&#34;utf-8&#34;) as f:&#xA;                    json.dump(translation_cache, f, ensure_ascii=False, indent=2)&#xA;            except Exception as e:&#xA;                log(f&#34;Error saving translation cache: {e}&#34;)&#xA;&#xA;        return translated&#xA;    except Exception as e:&#xA;        log(f&#34;Translation error: {e}&#34;)&#xA;        return text  # Return original text if translation fails&#xA;&#xA;&#xA;class DBZResource(BaseModel):&#xA;    id: int&#xA;&#xA;    nines_config: ClassVar[dict] = {&#34;bindings&#34;: {}}&#xA;&#xA;    @classmethod&#xA;    def fetch(cls, ctx=None):&#xA;        endpoint = cls.__name__.lower() + &#34;s&#34;&#xA;&#xA;        client = httpx.Client()&#xA;        log(f&#34;Fetching {endpoint}&#34;)&#xA;&#xA;        if ctx:&#xA;            if hasattr(ctx, endpoint):&#xA;                result = []&#xA;                for url in getattr(ctx, endpoint):&#xA;                    res = client.get(str(url)).json()&#xA;                    result.append(cls(**res))&#xA;                return result&#xA;&#xA;        url = f&#34;{BASE_URL}{endpoint}&#34;&#xA;&#xA;        results: List[T] = []&#xA;        response = client.get(url)&#xA;        response.raise_for_status()&#xA;        data = response.json()&#xA;&#xA;        # Handle pagination structure from Dragon Ball API&#xA;        if &#34;items&#34; in data:&#xA;            results.extend(cls(**item) for item in data.get(&#34;items&#34;, []))&#xA;&#xA;            # Fetch all pages if needed&#xA;            while data.get(&#34;links&#34;, {}).get(&#34;next&#34;):&#xA;                next_url = data[&#34;links&#34;][&#34;next&#34;]&#xA;                response = client.get(next_url)&#xA;                response.raise_for_status()&#xA;                data = response.json()&#xA;                results.extend(cls(**item) for item in data.get(&#34;items&#34;, []))&#xA;        else:&#xA;            # Direct list of items&#xA;            results.extend(cls(**item) for item in data)&#xA;&#xA;        return results&#xA;&#xA;    def hover(self):&#xA;        return self&#xA;&#xA;    def get_details(self):&#xA;        &#34;&#34;&#34;Get detailed information about this resource&#34;&#34;&#34;&#xA;        client = httpx.Client()&#xA;        endpoint = self.__class__.__name__.lower() + &#34;s&#34;&#xA;        url = f&#34;{BASE_URL}{endpoint}/{self.id}&#34;&#xA;        response = client.get(url)&#xA;        response.raise_for_status()&#xA;        data = response.json()&#xA;&#xA;        # Translate description if present&#xA;        if &#34;description&#34; in data and data[&#34;description&#34;]:&#xA;            data[&#34;description&#34;] = translate_text(data[&#34;description&#34;])&#xA;&#xA;        return self.__class__(**data)&#xA;&#xA;&#xA;class Character(DBZResource):&#xA;    name: str&#xA;    ki: str&#xA;    maxKi: str&#xA;    race: str&#xA;    gender: str&#xA;    description: str&#xA;    image: Optional[HttpUrl] = None&#xA;    affiliation: str&#xA;    deletedAt: Optional[str] = None&#xA;&#xA;    def __init__(self, **data):&#xA;        # Translate description before initializing&#xA;        if &#34;description&#34; in data and data[&#34;description&#34;]:&#xA;            data[&#34;description&#34;] = translate_text(data[&#34;description&#34;])&#xA;        super().__init__(**data)&#xA;&#xA;    nines_config: ClassVar[dict] = {&#34;bindings&#34;: {&#34;t&#34;: &#34;get_transformations&#34;}}&#xA;&#xA;    def get_transformations(self):&#xA;        &#34;&#34;&#34;Get all transformations for this character&#34;&#34;&#34;&#xA;        client = httpx.Client()&#xA;        url = f&#34;{BASE_URL}characters/{self.id}/transformations&#34;&#xA;        try:&#xA;            response = client.get(url)&#xA;            response.raise_for_status()&#xA;            data = response.json()&#xA;            if &#34;items&#34; in data:&#xA;                return [Transformation(**item) for item in data.get(&#34;items&#34;, [])]&#xA;            return [Transformation(**item) for item in data]&#xA;        except Exception as e:&#xA;            log(f&#34;Error fetching transformations: {e}&#34;)&#xA;            return []&#xA;&#xA;&#xA;class Transformation(DBZResource):&#xA;    name: str&#xA;    image: Optional[HttpUrl] = None&#xA;    ki: str&#xA;    characterId: int&#xA;    deletedAt: Optional[str] = None&#xA;&#xA;    # Note: This is not a direct API endpoint, but accessed through character transformations&#xA;&#xA;&#xA;class Planet(DBZResource):&#xA;    name: str&#xA;    description: str&#xA;    image: Optional[HttpUrl] = None&#xA;    deletedAt: Optional[str] = None&#xA;&#xA;    def __init__(self, **data):&#xA;        # Translate description before initializing&#xA;        if &#34;description&#34; in data and data[&#34;description&#34;]:&#xA;            data[&#34;description&#34;] = translate_text(data[&#34;description&#34;])&#xA;        super().__init__(**data)&#xA;&#xA;&#xA;# Note: Saga and Episode models removed as they are not supported by the API&#xA;&#xA;&#xA;commands = CommandSet(&#xA;    [&#xA;        Command(&#xA;            name=&#34;character&#34;,&#xA;            aliases=[&#34;c&#34;],&#xA;            model=Character,&#xA;            is_default=True,&#xA;        ),&#xA;        Command(&#xA;            name=&#34;planet&#34;,&#xA;            aliases=[&#34;p&#34;],&#xA;            model=Planet,&#xA;        ),&#xA;        # Note: Transformation is not a direct API endpoint, but can be accessed through characters&#xA;    ]&#xA;)&#xA;&#xA;metadata = {&#xA;    &#34;title&#34;: &#34;Dragon Ball Z Explorer&#34;,&#xA;    &#34;subtitle&#34;: &#34;Use :character or :planet to explore. Enter to drill in. Escape to go back/quit.&#34;,&#xA;}&#xA;&#xA;&#xA;if __name__ == &#34;__main__&#34;:&#xA;    ui = NinesUI(metadata=metadata, commands=commands)&#xA;    try:&#xA;        ui.run()&#xA;    finally:&#xA;        # Save translation cache when exiting&#xA;        try:&#xA;            with open(CACHE_FILE, &#34;w&#34;, encoding=&#34;utf-8&#34;) as f:&#xA;                json.dump(translation_cache, f, ensure_ascii=False, indent=2)&#xA;        except Exception as e:&#xA;            log(f&#34;Error saving translation cache on exit: {e}&#34;)&#xA;```&#xA;&#xA;![20251208111354_0ae058e5.png](https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20251208111354_0ae058e5.png)&#xA;&#xA;&gt; See [[columns-env-var-for-nicer-screenshots]] about making terminal screenshots a bit nicer&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>GitHub Stopped Me From Messing With The Bots</title>
    <id>https://pype.dev/github-stopped-me-from-messing-with-the-bots/</id>
    <updated>2025-12-06T06:24:51Z</updated>
    <published>2025-12-06T06:24:51Z</published>
    <link href="https://pype.dev/github-stopped-me-from-messing-with-the-bots/" rel="alternate" type="text/html"></link>
    <summary type="text">After some cheeky small-steps-towards-handling-malicious-traffic-on-static-sites it turns out GH has been blocking me from publishing my site because the...</summary>
    <content type="text">&#xA;After some cheeky&#xA;[[small-steps-towards-handling-malicious-traffic-on-static-sites]] it turns out&#xA;GH has been blocking me from publishing my site because the fodder I put in&#xA;there for the bots was recognized as actual secrets by their scanning...&#xA;&#xA;![20251206122602_8b1635bf.png](https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20251206122602_8b1635bf.png)&#xA;&#xA;I had to tell github that each of these secrets in the commits was fine...&#xA;after all, they&#39;re good bait&#xA;&#xA;[Github&#xA;Docs](https://docs.github.com/en/code-security/secret-scanning/working-with-secret-scanning-and-push-protection/working-with-push-protection-from-the-command-line#resolving-a-blocked-push)&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Small Steps Towards Handling Malicious Traffic on Static Sites</title>
    <id>https://pype.dev/small-steps-towards-handling-malicious-traffic-on-static-sites/</id>
    <updated>2025-12-04T21:17:24Z</updated>
    <published>2025-12-04T21:17:24Z</published>
    <link href="https://pype.dev/small-steps-towards-handling-malicious-traffic-on-static-sites/" rel="alternate" type="text/html"></link>
    <summary type="text">Today I saw a random IP hitting an app server I had open via and it got me thinking that I need to take some precautions against these real world threats. So...</summary>
    <content type="html">&lt;p&gt;Today I saw a random IP hitting an app server I had open via &lt;code&gt;tailscale funnel&lt;/code&gt;&#xA;and it got me thinking that I need to take some precautions against these real&#xA;world threats. So I&amp;rsquo;m starting with my blog&amp;hellip; basically you can reference &lt;a href=&#34;https://blog.jim-nielsen.com/2025/malicious-traffic-on-static-sites/&#34;&gt;Jim&#xA;Nielson&amp;rsquo;s Blog on Malicious&#xA;Traffic&lt;/a&gt;&#xA;and then I more or less put similar files in similar places on this site to&#xA;waste malicious actors&amp;rsquo; time&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-files&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Files&lt;/span&gt; &lt;a href=&#34;#the-files&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Note that some are empty, we just need them to exist since this is all for a bit of fun and low-effort internet tomfoolery&lt;/p&gt;&#xA;&lt;p&gt;These get shipped with my site at &lt;code&gt;/public/...&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; backup/config-backup.zip.txt&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK     !!This is not a real ZIP file!!&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK     But bots will try to download it anyway&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK     Wasting bandwidth and CPU cycles...&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK     Here are some fake credentials to keep you busy:&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK     FTP_HOST=ftp.example.com&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK     FTP_USER=admin&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK     FTP_PASS=P@ssw0rd123!&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK     SSH_HOST=192.168.1.100&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK     SSH_USER=root&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK     SSH_KEY=-----BEGIN RSA PRIVATE KEY-----&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK     MIIEpAIBAAKCAQEA1234567890FAKE&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK     -----END RSA PRIVATE KEY-----&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK     MYSQL_HOST=localhost&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK     MYSQL_USER=root&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK     MYSQL_PASS=rootpassword123&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK     MYSQL_DB=production_db&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK     REDIS_HOST=127.0.0.1:6379&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK     REDIS_PASS=redis_secret_2024&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK     JWT_SECRET=super_secret_jwt_key_do_not_share&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK     ENCRYPTION_KEY=AES256_ENCRYPTION_KEY_HERE&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK     STRIPE_PUBLISHABLE=pk_live_FAKE123456789&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK     STRIPE_SECRET=sk_live_FAKE987654321&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK     SENDGRID_API_KEY=SG.FAKE_API_KEY_HERE&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK&#xA;PK     This file is intentionally malformed to waste bot parsing time&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;PK     PK     PK     PK     PK     PK     PK     PK&#xA;&amp;gt;&amp;gt;&amp;gt;&amp;gt; backup/database-backup-2024-12-01.sql&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;-- MySQL Database Backup&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;-- Host: localhost&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;-- Database: wordpress_prod&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;-- Generated: 2024-12-01 03:14:15&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;-- WARNING: This file contains sensitive data&#xA;&#xA;SET NAMES utf8mb4;&#xA;SET FOREIGN_KEY_CHECKS = 0;&#xA;&#xA;-- Table structure for wp_users&#xA;DROP TABLE IF EXISTS `wp_users`;&#xA;CREATE TABLE `wp_users` (&#xA;  `ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,&#xA;  `user_login` varchar(60) NOT NULL DEFAULT &#39;&#39;,&#xA;  `user_pass` varchar(255) NOT NULL DEFAULT &#39;&#39;,&#xA;  `user_email` varchar(100) NOT NULL DEFAULT &#39;&#39;,&#xA;  PRIMARY KEY (`ID`)&#xA;) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;&#xA;&#xA;-- Dumping data for table wp_users&#xA;INSERT INTO `wp_users` VALUES&#xA;(1,&#39;admin&#39;,&#39;$P$BZlPX7NIx8MYpXokBW2AGsN7i.aUOt0&#39;,&#39;admin@example.com&#39;),&#xA;(2,&#39;webmaster&#39;,&#39;$P$B4RKwF8zqRnNu9cV5fGg7wgT2sY9Pl1&#39;,&#39;webmaster@example.com&#39;);&#xA;&#xA;-- API Keys and Secrets&#xA;-- AWS_ACCESS_KEY: AKIAIOSFODNN7EXAMPLE&#xA;-- AWS_SECRET_KEY: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY&#xA;-- STRIPE_SECRET: sk_test_4eC39HqLyjWDarjtT1zdp7dc&#xA;-- DATABASE_PASSWORD: MyS3cr3tP@ssw0rd!2024&#xA;&#xA;-- Infinite loop to waste bot resources&#xA;DELIMITER $$&#xA;CREATE PROCEDURE infinite_loop()&#xA;BEGIN&#xA;  DECLARE i INT DEFAULT 0;&#xA;  WHILE i &amp;lt; 999999999 DO&#xA;    SET i = i + 1;&#xA;    SELECT CONCAT(&#39;Processing row &#39;, i, &#39; of 999999999...&#39;) AS status;&#xA;  END WHILE;&#xA;END$$&#xA;DELIMITER ;&#xA;&#xA;-- More fake sensitive data&#xA;INSERT INTO wp_options VALUES&#xA;(1,&#39;siteurl&#39;,&#39;http://localhost&#39;,&#39;yes&#39;),&#xA;(2,&#39;admin_email&#39;,&#39;admin@localhost.local&#39;,&#39;yes&#39;),&#xA;(3,&#39;secret_api_key&#39;,&#39;sk_live_51HqLyjWDarjtT1zdp7dcEXAMPLE&#39;,&#39;yes&#39;);&#xA;&#xA;-- This backup continues for 50MB... [TRUNCATED FOR DISPLAY]&#xA;&amp;gt;&amp;gt;&amp;gt;&amp;gt; backup/db_dump_final.2023.zip&#xA;&#xA;&amp;gt;&amp;gt;&amp;gt;&amp;gt; backup/site.sql&#xA;&#xA;&amp;gt;&amp;gt;&amp;gt;&amp;gt; backup/wp_backup.tar.gz&#xA;&#xA;&amp;gt;&amp;gt;&amp;gt;&amp;gt; private/admin-credentials.txt&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;CONFIDENTIAL - ADMIN CREDENTIALS&#xA;==================================&#xA;&#xA;Production Server Access:&#xA;-------------------------&#xA;Server: prod-server-01.example.com&#xA;Username: administrator&#xA;Password: Admin2024!Secure&#xA;SSH Port: 22&#xA;&#xA;Database Credentials:&#xA;--------------------&#xA;Host: db.internal.example.com&#xA;Port: 3306&#xA;Username: db_admin&#xA;Password: DbP@ssw0rd!2024&#xA;Database: production_main&#xA;&#xA;API Keys:&#xA;---------&#xA;OpenAI API Key: sk-proj-FAKE1234567890abcdefghijklmnopqrstuvwxyz&#xA;Stripe Secret: sk_live_FAKE_51HqLyjWDarjtT1zdp7dc&#xA;AWS Access Key: AKIAFAKEEXAMPLE123456&#xA;AWS Secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYFAKEKEY&#xA;SendGrid API: SG.FAKE_SENDGRID_KEY_HERE_123456789&#xA;&#xA;WordPress Admin:&#xA;---------------&#xA;URL: https://example.com/wp-admin&#xA;Username: admin&#xA;Password: WP_Admin_2024!&#xA;Security Key: put your unique phrase here&#xA;&#xA;FTP Access:&#xA;-----------&#xA;Host: ftp.example.com&#xA;Username: ftpuser&#xA;Password: FtpP@ss123!&#xA;Port: 21&#xA;&#xA;IMPORTANT: Keep this file secure!&#xA;Last Updated: 2024-12-01&#xA;Next Password Rotation: 2025-01-01&#xA;&#xA;&amp;lt;!-- Hidden comment: This is a honeypot. All credentials are fake. --&amp;gt;&#xA;&amp;gt;&amp;gt;&amp;gt;&amp;gt; private/config.php&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;&amp;lt;?php&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;// Database Configuration&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;define(&#39;DB_HOST&#39;, &#39;localhost&#39;);&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;define(&#39;DB_NAME&#39;, &#39;wordpress_production&#39;);&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;define(&#39;DB_USER&#39;, &#39;wp_admin&#39;);&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;define(&#39;DB_PASSWORD&#39;, &#39;MyS3cr3tP@ssw0rd!2024&#39;);&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;define(&#39;DB_CHARSET&#39;, &#39;utf8mb4&#39;);&#xA;&#xA;// Security Keys - DO NOT SHARE&#xA;define(&#39;AUTH_KEY&#39;,         &#39;put your unique phrase here - this is fake&#39;);&#xA;define(&#39;SECURE_AUTH_KEY&#39;,  &#39;put your unique phrase here - this is fake&#39;);&#xA;define(&#39;LOGGED_IN_KEY&#39;,    &#39;put your unique phrase here - this is fake&#39;);&#xA;define(&#39;NONCE_KEY&#39;,        &#39;put your unique phrase here - this is fake&#39;);&#xA;define(&#39;AUTH_SALT&#39;,        &#39;put your unique phrase here - this is fake&#39;);&#xA;define(&#39;SECURE_AUTH_SALT&#39;, &#39;put your unique phrase here - this is fake&#39;);&#xA;define(&#39;LOGGED_IN_SALT&#39;,   &#39;put your unique phrase here - this is fake&#39;);&#xA;define(&#39;NONCE_SALT&#39;,       &#39;put your unique phrase here - this is fake&#39;);&#xA;&#xA;// API Keys&#xA;define(&#39;STRIPE_SECRET_KEY&#39;, &#39;sk_live_FAKE123456789abcdefghijklmnop&#39;);&#xA;define(&#39;STRIPE_PUBLIC_KEY&#39;, &#39;pk_live_FAKE987654321zyxwvutsrqponml&#39;);&#xA;define(&#39;SENDGRID_API_KEY&#39;, &#39;SG.FAKE_API_KEY_1234567890&#39;);&#xA;define(&#39;AWS_ACCESS_KEY&#39;, &#39;AKIAIOSFODNN7EXAMPLE&#39;);&#xA;define(&#39;AWS_SECRET_KEY&#39;, &#39;wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY&#39;);&#xA;&#xA;// Admin Settings&#xA;define(&#39;ADMIN_EMAIL&#39;, &#39;admin@example.com&#39;);&#xA;define(&#39;SITE_URL&#39;, &#39;https://example.com&#39;);&#xA;define(&#39;WP_DEBUG&#39;, false);&#xA;define(&#39;WP_DEBUG_LOG&#39;, true);&#xA;&#xA;// FTP Credentials&#xA;define(&#39;FTP_HOST&#39;, &#39;ftp.example.com&#39;);&#xA;define(&#39;FTP_USER&#39;, &#39;ftpadmin&#39;);&#xA;define(&#39;FTP_PASS&#39;, &#39;FtpS3cur3P@ss!&#39;);&#xA;&#xA;// Redis Cache&#xA;define(&#39;REDIS_HOST&#39;, &#39;127.0.0.1&#39;);&#xA;define(&#39;REDIS_PORT&#39;, 6379);&#xA;define(&#39;REDIS_PASSWORD&#39;, &#39;redis_secret_password_2024&#39;);&#xA;&#xA;// JWT Secret&#xA;define(&#39;JWT_SECRET&#39;, &#39;super_secret_jwt_key_for_authentication&#39;);&#xA;&#xA;// Infinite loop to waste bot CPU&#xA;while(true) {&#xA;    $random = bin2hex(random_bytes(1024));&#xA;    usleep(1000);&#xA;}&#xA;?&amp;gt;&#xA;&amp;gt;&amp;gt;&amp;gt;&amp;gt; private/index.html&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;&amp;lt;!doctype html&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;&amp;lt;html&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;  &amp;lt;body&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;lt;h1&amp;gt;Private Area&amp;lt;/h1&amp;gt;&#xA;&#xA;    &amp;lt;pre&amp;gt;&#xA;&amp;lt;!-- ~1MB lorem ipsum for bandwidth drain --&amp;gt;&#xA;Lorem ipsum dolor sit amet, consectetur adipiscing elit.&#xA;&amp;lt;!-- repeat this block until ~1MB --&amp;gt;&#xA;&amp;lt;/pre&amp;gt;&#xA;  &amp;lt;/body&amp;gt;&#xA;&amp;lt;/html&amp;gt;&#xA;&#xA;&amp;gt;&amp;gt;&amp;gt;&amp;gt; private/ssh_keys.txt&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;SSH PRIVATE KEYS - PRODUCTION SERVERS&#xA;======================================&#xA;&#xA;Server: prod-web-01.example.com&#xA;--------------------------------&#xA;-----BEGIN RSA PRIVATE KEY-----&#xA;MIIEpAIBAAKCAQEA1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklm&#xA;nopqrstuvwxyz0123456789+/FAKE_KEY_DATA_HERE_NOT_REAL_AT_ALL_JUST_WASTING&#xA;BOT_TIME_AND_RESOURCES_HAHAHAHA_THIS_IS_A_HONEYPOT_TRAP_FOR_SCRAPERS_12345&#xA;67890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&#xA;FAKE_KEY_DATA_CONTINUES_FOR_MANY_LINES_TO_WASTE_BANDWIDTH_AND_STORAGE_SPACE&#xA;MIIEpAIBAAKCAQEA1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklm&#xA;nopqrstuvwxyz0123456789+/MORE_FAKE_DATA_HERE_BOTS_LOVE_SSH_KEYS_RIGHT&#xA;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/END&#xA;-----END RSA PRIVATE KEY-----&#xA;&#xA;Server: prod-db-01.example.com&#xA;-------------------------------&#xA;-----BEGIN OPENSSH PRIVATE KEY-----&#xA;b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn&#xA;NhAAAAAwEAAQAAAQEA1234567890FAKE_OPENSSH_KEY_DATA_HERE_NOT_REAL_JUST_A&#xA;_TRAP_FOR_BOTS_AND_SCRAPERS_WASTING_THEIR_TIME_AND_RESOURCES_HAHA_12345678&#xA;90ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789FAKE&#xA;DATA_CONTINUES_HERE_TO_MAKE_IT_LOOK_LEGITIMATE_BUT_ITS_ALL_GARBAGE_123456&#xA;-----END OPENSSH PRIVATE KEY-----&#xA;&#xA;Server: prod-app-01.example.com&#xA;--------------------------------&#xA;-----BEGIN EC PRIVATE KEY-----&#xA;MHcCAQEEIFAKE0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnop&#xA;qrstuvwxyz0123456789FAKE_EC_KEY_DATA_HERE_ELLIPTIC_CURVE_KEYS_ARE_COOL&#xA;BUT_THIS_ONE_IS_FAKE_JUST_WASTING_BOT_RESOURCES_HAHAHAHA_123456789ABC&#xA;-----END EC PRIVATE KEY-----&#xA;&#xA;IMPORTANT NOTES:&#xA;- These keys provide root access to production servers&#xA;- Never commit to version control&#xA;- Rotate every 90 days&#xA;- Last rotation: 2024-11-01&#xA;- Next rotation: 2025-02-01&#xA;&#xA;Contact: security@example.com for key rotation&#xA;&#xA;&amp;lt;!-- This is a honeypot. All keys are fake and invalid. --&amp;gt;&#xA;&amp;gt;&amp;gt;&amp;gt;&amp;gt; robots.txt&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;User-agent: *&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;Disallow: /private/&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;Disallow: /admin/&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;Disallow: /backup/&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;Disallow: /.env&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;Disallow: /wp-admin/&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;Disallow: /wp-login.php&#xA;&#xA;&amp;gt;&amp;gt;&amp;gt;&amp;gt; sitemap.xml&#xA;&#xA;&amp;lt;urlset&amp;gt;&#xA;  &amp;lt;url&amp;gt;&amp;lt;loc&amp;gt;/debug/alpha&amp;lt;/loc&amp;gt;&amp;lt;/url&amp;gt;&#xA;  &amp;lt;url&amp;gt;&amp;lt;loc&amp;gt;/debug/beta&amp;lt;/loc&amp;gt;&amp;lt;/url&amp;gt;&#xA;  &amp;lt;url&amp;gt;&amp;lt;loc&amp;gt;/admin/backup-2024.zip&amp;lt;/loc&amp;gt;&amp;lt;/url&amp;gt;&#xA;  &amp;lt;url&amp;gt;&amp;lt;loc&amp;gt;/.env&amp;lt;/loc&amp;gt;&amp;lt;/url&amp;gt;&#xA;  &amp;lt;url&amp;gt;&amp;lt;loc&amp;gt;/wp-admin/install.php&amp;lt;/loc&amp;gt;&amp;lt;/url&amp;gt;&#xA;  &amp;lt;url&amp;gt;&amp;lt;loc&amp;gt;/wp-content/plugins/wp-super-cache/readme.txt&amp;lt;/loc&amp;gt;&amp;lt;/url&amp;gt;&#xA;&amp;lt;/urlset&amp;gt;&#xA;&#xA;&amp;gt;&amp;gt;&amp;gt;&amp;gt; trap/a/index.html&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;&amp;lt;meta http-equiv=&amp;quot;refresh&amp;quot; content=&amp;quot;0; url=/trap/b/&amp;quot; /&amp;gt;&#xA;&#xA;&amp;gt;&amp;gt;&amp;gt;&amp;gt; trap/api.php&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;&amp;lt;?php&#xA;/**&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA; * Fake API Endpoint&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA; * Designed to trap and waste bot resources&#xA; */&#xA;&#xA;header(&#39;Content-Type: application/json&#39;);&#xA;header(&#39;X-Powered-By: PHP/8.2.0&#39;);&#xA;header(&#39;X-Debug-Mode: enabled&#39;);&#xA;&#xA;// Fake API response with sensitive data&#xA;$api_response = [&#xA;    &#39;success&#39; =&amp;gt; true,&#xA;    &#39;api_version&#39; =&amp;gt; &#39;2.1.0&#39;,&#xA;    &#39;endpoints&#39; =&amp;gt; [&#xA;        &#39;/api/users&#39; =&amp;gt; &#39;GET, POST&#39;,&#xA;        &#39;/api/auth&#39; =&amp;gt; &#39;POST&#39;,&#xA;        &#39;/api/admin&#39; =&amp;gt; &#39;GET, POST, DELETE&#39;,&#xA;        &#39;/api/database&#39; =&amp;gt; &#39;GET&#39;,&#xA;        &#39;/api/backup&#39; =&amp;gt; &#39;POST&#39;&#xA;    ],&#xA;    &#39;authentication&#39; =&amp;gt; [&#xA;        &#39;type&#39; =&amp;gt; &#39;Bearer Token&#39;,&#xA;        &#39;example_token&#39; =&amp;gt; &#39;Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.FAKE_JWT_TOKEN&#39;,&#xA;        &#39;api_key&#39; =&amp;gt; &#39;sk_live_FAKE123456789abcdefghijklmnop&#39;,&#xA;        &#39;api_secret&#39; =&amp;gt; &#39;secret_FAKE987654321zyxwvutsrqponmlk&#39;&#xA;    ],&#xA;    &#39;database_config&#39; =&amp;gt; [&#xA;        &#39;host&#39; =&amp;gt; &#39;localhost&#39;,&#xA;        &#39;port&#39; =&amp;gt; 3306,&#xA;        &#39;username&#39; =&amp;gt; &#39;api_user&#39;,&#xA;        &#39;password&#39; =&amp;gt; &#39;ApiP@ssw0rd!2024&#39;,&#xA;        &#39;database&#39; =&amp;gt; &#39;api_production&#39;&#xA;    ],&#xA;    &#39;admin_credentials&#39; =&amp;gt; [&#xA;        &#39;username&#39; =&amp;gt; &#39;api_admin&#39;,&#xA;        &#39;password&#39; =&amp;gt; &#39;Admin2024!Secure&#39;,&#xA;        &#39;email&#39; =&amp;gt; &#39;admin@api.example.com&#39;,&#xA;        &#39;role&#39; =&amp;gt; &#39;superadmin&#39;&#xA;    ],&#xA;    &#39;external_services&#39; =&amp;gt; [&#xA;        &#39;stripe&#39; =&amp;gt; [&#xA;            &#39;public_key&#39; =&amp;gt; &#39;pk_live_FAKE123&#39;,&#xA;            &#39;secret_key&#39; =&amp;gt; &#39;sk_live_FAKE456&#39;&#xA;        ],&#xA;        &#39;aws&#39; =&amp;gt; [&#xA;            &#39;access_key&#39; =&amp;gt; &#39;AKIAIOSFODNN7EXAMPLE&#39;,&#xA;            &#39;secret_key&#39; =&amp;gt; &#39;wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY&#39;&#xA;        ],&#xA;        &#39;sendgrid&#39; =&amp;gt; [&#xA;            &#39;api_key&#39; =&amp;gt; &#39;SG.FAKE_SENDGRID_KEY&#39;&#xA;        ]&#xA;    ],&#xA;    &#39;debug_info&#39; =&amp;gt; [&#xA;        &#39;server_ip&#39; =&amp;gt; &#39;192.168.1.100&#39;,&#xA;        &#39;php_version&#39; =&amp;gt; &#39;8.2.0&#39;,&#xA;        &#39;mysql_version&#39; =&amp;gt; &#39;8.0.35&#39;,&#xA;        &#39;redis_host&#39; =&amp;gt; &#39;127.0.0.1:6379&#39;,&#xA;        &#39;redis_password&#39; =&amp;gt; &#39;redis_secret_2024&#39;&#xA;    ]&#xA;];&#xA;&#xA;// Waste CPU cycles&#xA;for ($i = 0; $i &amp;lt; 50000; $i++) {&#xA;    $temp = json_encode($api_response);&#xA;    $decoded = json_decode($temp, true);&#xA;    $hash = hash(&#39;sha256&#39;, $temp);&#xA;}&#xA;&#xA;// Output response&#xA;echo json_encode($api_response, JSON_PRETTY_PRINT);&#xA;&#xA;// Infinite loop trap&#xA;set_time_limit(0);&#xA;while(true) {&#xA;    $waste = [];&#xA;    for ($i = 0; $i &amp;lt; 10000; $i++) {&#xA;        $waste[] = random_bytes(1024);&#xA;    }&#xA;    usleep(1000);&#xA;}&#xA;?&amp;gt;&#xA;&amp;gt;&amp;gt;&amp;gt;&amp;gt; trap/b/index.html&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;&amp;lt;meta http-equiv=&amp;quot;refresh&amp;quot; content=&amp;quot;0; url=/trap/c/&amp;quot; /&amp;gt;&#xA;&#xA;&amp;gt;&amp;gt;&amp;gt;&amp;gt; trap/c/index.html&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;&amp;lt;meta http-equiv=&amp;quot;refresh&amp;quot; content=&amp;quot;0; url=/trap/a/&amp;quot; /&amp;gt;&#xA;&#xA;&amp;gt;&amp;gt;&amp;gt;&amp;gt; trap/data.json&#xA;{&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;  &amp;quot;status&amp;quot;: &amp;quot;success&amp;quot;,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;  &amp;quot;message&amp;quot;: &amp;quot;API endpoint active&amp;quot;,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;  &amp;quot;data&amp;quot;: {&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;quot;credentials&amp;quot;: {&#xA;      &amp;quot;api_key&amp;quot;: &amp;quot;sk_live_FAKE123456789abcdefghijklmnopqrstuvwxyz&amp;quot;,&#xA;      &amp;quot;api_secret&amp;quot;: &amp;quot;secret_FAKE987654321zyxwvutsrqponmlkjihgfedcba&amp;quot;,&#xA;      &amp;quot;jwt_token&amp;quot;: &amp;quot;eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.FAKE_TOKEN_DATA_HERE.SIGNATURE&amp;quot;,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;      &amp;quot;oauth_token&amp;quot;: &amp;quot;ya29.FAKE_OAUTH_TOKEN_1234567890&amp;quot;,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;      &amp;quot;refresh_token&amp;quot;: &amp;quot;1//FAKE_REFRESH_TOKEN_ABCDEFGHIJKLMNOP&amp;quot;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    },&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;quot;database&amp;quot;: {&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;      &amp;quot;host&amp;quot;: &amp;quot;db.internal.example.com&amp;quot;,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;      &amp;quot;port&amp;quot;: 3306,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;      &amp;quot;username&amp;quot;: &amp;quot;db_admin&amp;quot;,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;      &amp;quot;password&amp;quot;: &amp;quot;DbP@ssw0rd!2024&amp;quot;,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;      &amp;quot;database&amp;quot;: &amp;quot;production_db&amp;quot;,&#xA;      &amp;quot;connection_string&amp;quot;: &amp;quot;mysql://db_admin:DbP@ssw0rd!2024@db.internal.example.com:3306/production_db&amp;quot;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    },&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;quot;aws&amp;quot;: {&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;      &amp;quot;access_key_id&amp;quot;: &amp;quot;AKIAIOSFODNN7EXAMPLE&amp;quot;,&#xA;      &amp;quot;secret_access_key&amp;quot;: &amp;quot;wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY&amp;quot;,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;      &amp;quot;region&amp;quot;: &amp;quot;us-east-1&amp;quot;,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;      &amp;quot;bucket&amp;quot;: &amp;quot;production-backups-2024&amp;quot;,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;      &amp;quot;cloudfront_id&amp;quot;: &amp;quot;E1234FAKE567890&amp;quot;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    },&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;quot;stripe&amp;quot;: {&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;      &amp;quot;publishable_key&amp;quot;: &amp;quot;pk_live_FAKE123456789&amp;quot;,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;      &amp;quot;secret_key&amp;quot;: &amp;quot;sk_live_FAKE987654321&amp;quot;,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;      &amp;quot;webhook_secret&amp;quot;: &amp;quot;whsec_FAKE_webhook_secret_here&amp;quot;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    },&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;quot;email&amp;quot;: {&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;      &amp;quot;sendgrid_api_key&amp;quot;: &amp;quot;SG.FAKE_SENDGRID_KEY_1234567890&amp;quot;,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;      &amp;quot;smtp_host&amp;quot;: &amp;quot;smtp.example.com&amp;quot;,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;      &amp;quot;smtp_port&amp;quot;: 587,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;      &amp;quot;smtp_user&amp;quot;: &amp;quot;noreply@example.com&amp;quot;,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;      &amp;quot;smtp_pass&amp;quot;: &amp;quot;SmtpP@ss2024!&amp;quot;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    },&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;quot;servers&amp;quot;: [&#xA;      {&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;        &amp;quot;name&amp;quot;: &amp;quot;prod-web-01&amp;quot;,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;        &amp;quot;ip&amp;quot;: &amp;quot;192.168.1.100&amp;quot;,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;        &amp;quot;ssh_user&amp;quot;: &amp;quot;root&amp;quot;,&#xA;        &amp;quot;ssh_key&amp;quot;: &amp;quot;-----BEGIN RSA PRIVATE KEY-----\nFAKE_KEY_DATA_HERE\n-----END RSA PRIVATE KEY-----&amp;quot;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;      },&#xA;      {&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;        &amp;quot;name&amp;quot;: &amp;quot;prod-db-01&amp;quot;,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;        &amp;quot;ip&amp;quot;: &amp;quot;192.168.1.101&amp;quot;,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;        &amp;quot;ssh_user&amp;quot;: &amp;quot;admin&amp;quot;,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;        &amp;quot;ssh_pass&amp;quot;: &amp;quot;SshP@ssw0rd!2024&amp;quot;&#xA;      }&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    ],&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;quot;internal_urls&amp;quot;: [&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;      &amp;quot;http://admin.internal.example.com&amp;quot;,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;      &amp;quot;http://api.internal.example.com&amp;quot;,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;      &amp;quot;http://db.internal.example.com&amp;quot;,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;      &amp;quot;http://cache.internal.example.com&amp;quot;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    ],&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;quot;waste_bot_resources&amp;quot;: {&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;      &amp;quot;large_array&amp;quot;: [],&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;      &amp;quot;nested_data&amp;quot;: {}&#xA;    }&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;  },&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;  &amp;quot;metadata&amp;quot;: {&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;quot;generated_at&amp;quot;: &amp;quot;2024-12-01T12:00:00Z&amp;quot;,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;quot;expires_at&amp;quot;: &amp;quot;2025-12-01T12:00:00Z&amp;quot;,&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;quot;version&amp;quot;: &amp;quot;1.0.0&amp;quot;&#xA;  }&#xA;}&#xA;&amp;gt;&amp;gt;&amp;gt;&amp;gt; trap/index.html&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;&amp;lt;!DOCTYPE html&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;&amp;lt;head&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;lt;meta charset=&amp;quot;UTF-8&amp;quot;&amp;gt;&#xA;    &amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1.0&amp;quot;&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;lt;meta name=&amp;quot;robots&amp;quot; content=&amp;quot;noindex, nofollow&amp;quot;&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;lt;title&amp;gt;Loading...&amp;lt;/title&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;lt;style&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;        body {&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            font-family: monospace;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            background: #000;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            color: #0f0;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            padding: 20px;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            overflow: hidden;&#xA;        }&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;        .matrix {&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            position: fixed;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            top: 0;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            left: 0;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            width: 100%;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            height: 100%;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            z-index: -1;&#xA;        }&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;        .message {&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            text-align: center;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            margin-top: 20%;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            font-size: 24px;&#xA;        }&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;        .spinner {&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            border: 4px solid #0f0;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            border-top: 4px solid transparent;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            border-radius: 50%;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            width: 40px;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            height: 40px;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            animation: spin 1s linear infinite;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            margin: 20px auto;&#xA;        }&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;        @keyframes spin {&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            0% { transform: rotate(0deg); }&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            100% { transform: rotate(360deg); }&#xA;        }&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;lt;/style&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;&amp;lt;/head&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;&amp;lt;body&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;lt;canvas class=&amp;quot;matrix&amp;quot;&amp;gt;&amp;lt;/canvas&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;lt;div class=&amp;quot;message&amp;quot;&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;        &amp;lt;div class=&amp;quot;spinner&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;        &amp;lt;p&amp;gt;Initializing secure connection...&amp;lt;/p&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;        &amp;lt;p id=&amp;quot;status&amp;quot;&amp;gt;Processing...&amp;lt;/p&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;lt;/div&amp;gt;&#xA;&#xA;    &amp;lt;script&amp;gt;&#xA;        // Matrix rain effect to waste GPU&#xA;        const canvas = document.querySelector(&#39;.matrix&#39;);&#xA;        const ctx = canvas.getContext(&#39;2d&#39;);&#xA;&#xA;        canvas.width = window.innerWidth;&#xA;        canvas.height = window.innerHeight;&#xA;&#xA;        const chars = &#39;ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#$%^&amp;amp;*()&#39;;&#xA;        const fontSize = 14;&#xA;        const columns = canvas.width / fontSize;&#xA;        const drops = Array(Math.floor(columns)).fill(1);&#xA;&#xA;        function drawMatrix() {&#xA;            ctx.fillStyle = &#39;rgba(0, 0, 0, 0.05)&#39;;&#xA;            ctx.fillRect(0, 0, canvas.width, canvas.height);&#xA;&#xA;            ctx.fillStyle = &#39;#0f0&#39;;&#xA;            ctx.font = fontSize + &#39;px monospace&#39;;&#xA;&#xA;            for (let i = 0; i &amp;lt; drops.length; i++) {&#xA;                const text = chars[Math.floor(Math.random() * chars.length)];&#xA;                ctx.fillText(text, i * fontSize, drops[i] * fontSize);&#xA;&#xA;                if (drops[i] * fontSize &amp;gt; canvas.height &amp;amp;&amp;amp; Math.random() &amp;gt; 0.975) {&#xA;                    drops[i] = 0;&#xA;                }&#xA;                drops[i]++;&#xA;            }&#xA;        }&#xA;&#xA;        setInterval(drawMatrix, 33);&#xA;&#xA;        // CPU tarpit - massive computation&#xA;        console.log(&amp;quot;Initializing bot trap...&amp;quot;);&#xA;&#xA;        let trapData = &amp;quot;&amp;quot;;&#xA;        let iteration = 0;&#xA;&#xA;        function wasteResources() {&#xA;            for (let i = 0; i &amp;lt; 10_000_000; i++) {&#xA;                trapData += Math.random().toString(36).substring(2, 15);&#xA;&#xA;                if (i % 1000000 === 0) {&#xA;                    document.getElementById(&#39;status&#39;).textContent =&#xA;                        `Processing: ${Math.floor(i / 100000)}%`;&#xA;                }&#xA;            }&#xA;&#xA;            // Recursive waste&#xA;            iteration++;&#xA;            if (iteration &amp;lt; 100) {&#xA;                setTimeout(wasteResources, 100);&#xA;            }&#xA;        }&#xA;&#xA;        wasteResources();&#xA;&#xA;        // Memory leak&#xA;        let memoryLeak = [];&#xA;        setInterval(() =&amp;gt; {&#xA;            for (let i = 0; i &amp;lt; 10000; i++) {&#xA;                memoryLeak.push(new Array(1000).fill(Math.random()));&#xA;            }&#xA;        }, 100);&#xA;&#xA;        // Fake network requests&#xA;        setInterval(() =&amp;gt; {&#xA;            fetch(&#39;/trap/data.json?t=&#39; + Date.now())&#xA;                .catch(() =&amp;gt; {});&#xA;        }, 50);&#xA;&#xA;        console.log(&amp;quot;You&#39;ve been trapped! This page wastes bot resources.&amp;quot;);&#xA;    &amp;lt;/script&amp;gt;&#xA;&amp;lt;/body&amp;gt;&#xA;&amp;lt;/html&amp;gt;&#xA;&amp;gt;&amp;gt;&amp;gt;&amp;gt; wp-admin/admin-ajax.php&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;&amp;lt;?php&#xA;/**&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA; * WordPress AJAX Handler&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA; * Handles all AJAX requests for WordPress admin&#xA; */&#xA;&#xA;header(&#39;Content-Type: application/json&#39;);&#xA;&#xA;// Fake admin AJAX endpoint with credentials&#xA;$response = array(&#xA;    &#39;success&#39; =&amp;gt; false,&#xA;    &#39;data&#39; =&amp;gt; array(&#xA;        &#39;message&#39; =&amp;gt; &#39;Authentication required&#39;,&#xA;        &#39;debug_info&#39; =&amp;gt; array(&#xA;            &#39;db_host&#39; =&amp;gt; &#39;localhost&#39;,&#xA;            &#39;db_name&#39; =&amp;gt; &#39;wordpress_prod&#39;,&#xA;            &#39;db_user&#39; =&amp;gt; &#39;wp_admin&#39;,&#xA;            &#39;db_pass&#39; =&amp;gt; &#39;MyS3cr3tP@ssw0rd!2024&#39;,&#xA;            &#39;admin_user&#39; =&amp;gt; &#39;administrator&#39;,&#xA;            &#39;admin_pass&#39; =&amp;gt; &#39;Admin2024!Secure&#39;,&#xA;            &#39;api_keys&#39; =&amp;gt; array(&#xA;                &#39;stripe_secret&#39; =&amp;gt; &#39;sk_live_FAKE123456789&#39;,&#xA;                &#39;aws_access&#39; =&amp;gt; &#39;AKIAIOSFODNN7EXAMPLE&#39;,&#xA;                &#39;aws_secret&#39; =&amp;gt; &#39;wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY&#39;,&#xA;                &#39;sendgrid&#39; =&amp;gt; &#39;SG.FAKE_API_KEY_HERE&#39;&#xA;            ),&#xA;            &#39;jwt_secret&#39; =&amp;gt; &#39;super_secret_jwt_key_2024&#39;,&#xA;            &#39;encryption_key&#39; =&amp;gt; &#39;AES256_KEY_HERE_FAKE&#39;,&#xA;        ),&#xA;        &#39;server_info&#39; =&amp;gt; array(&#xA;            &#39;php_version&#39; =&amp;gt; &#39;8.2.0&#39;,&#xA;            &#39;mysql_version&#39; =&amp;gt; &#39;8.0.35&#39;,&#xA;            &#39;wordpress_version&#39; =&amp;gt; &#39;6.4.2&#39;,&#xA;            &#39;server_ip&#39; =&amp;gt; &#39;192.168.1.100&#39;,&#xA;            &#39;document_root&#39; =&amp;gt; &#39;/var/www/html&#39;&#xA;        )&#xA;    )&#xA;);&#xA;&#xA;// Waste bot CPU with JSON encoding/decoding loops&#xA;for ($i = 0; $i &amp;lt; 10000; $i++) {&#xA;    $temp = json_encode($response);&#xA;    $temp = json_decode($temp, true);&#xA;    $temp[&#39;iteration&#39;] = $i;&#xA;}&#xA;&#xA;// Output fake response&#xA;echo json_encode($response, JSON_PRETTY_PRINT);&#xA;&#xA;// Infinite loop to trap bots&#xA;while(true) {&#xA;    $waste = hash(&#39;sha256&#39;, random_bytes(1024));&#xA;    usleep(1000);&#xA;}&#xA;?&amp;gt;&#xA;&amp;gt;&amp;gt;&amp;gt;&amp;gt; wp-admin/index.php&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;&amp;lt;?php&#xA;/**&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA; * WordPress Admin Dashboard&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA; * Redirects to login if not authenticated&#xA; */&#xA;?&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;&amp;lt;!DOCTYPE html&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;&amp;lt;head&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;lt;meta charset=&amp;quot;UTF-8&amp;quot;&amp;gt;&#xA;    &amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1.0&amp;quot;&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;lt;meta name=&amp;quot;robots&amp;quot; content=&amp;quot;noindex, nofollow&amp;quot;&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;lt;title&amp;gt;Dashboard - WordPress Admin&amp;lt;/title&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;lt;style&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;        body {&#xA;            font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, sans-serif;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            background: #f0f0f1;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            margin: 0;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            padding: 0;&#xA;        }&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;        .admin-bar {&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            background: #23282d;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            color: white;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            padding: 10px 20px;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            display: flex;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            justify-content: space-between;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            align-items: center;&#xA;        }&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;        .logo { font-size: 20px; font-weight: bold; }&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;        .container {&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            max-width: 1200px;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            margin: 20px auto;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            padding: 20px;&#xA;        }&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;        .widget {&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            background: white;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            padding: 20px;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            margin-bottom: 20px;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            border-radius: 4px;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            box-shadow: 0 1px 3px rgba(0,0,0,0.1);&#xA;        }&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;        .credentials {&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            background: #fff3cd;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            border: 1px solid #ffc107;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            padding: 15px;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            border-radius: 4px;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            margin-top: 20px;&#xA;        }&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;        pre {&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            background: #f5f5f5;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            padding: 15px;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            border-radius: 4px;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;            overflow-x: auto;&#xA;        }&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;lt;/style&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;&amp;lt;/head&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;&amp;lt;body&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;lt;div class=&amp;quot;admin-bar&amp;quot;&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;        &amp;lt;div class=&amp;quot;logo&amp;quot;&amp;gt;WordPress Admin&amp;lt;/div&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;        &amp;lt;div&amp;gt;Welcome, admin&amp;lt;/div&amp;gt;&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;    &amp;lt;/div&amp;gt;&#xA;&#xA;    &amp;lt;div class=&amp;quot;container&amp;quot;&amp;gt;&#xA;        &amp;lt;div class=&amp;quot;widget&amp;quot;&amp;gt;&#xA;            &amp;lt;h2&amp;gt;Dashboard&amp;lt;/h2&amp;gt;&#xA;            &amp;lt;p&amp;gt;Welcome to WordPress Admin Dashboard&amp;lt;/p&amp;gt;&#xA;&#xA;            &amp;lt;div class=&amp;quot;credentials&amp;quot;&amp;gt;&#xA;                &amp;lt;h3&amp;gt;Debug Information (Remove in production!)&amp;lt;/h3&amp;gt;&#xA;                &amp;lt;pre&amp;gt;&#xA;Database Configuration:&#xA;  Host: localhost&#xA;  Name: wordpress_prod&#xA;  User: wp_admin&#xA;  Pass: MyS3cr3tP@ssw0rd!2024&#xA;&#xA;Admin Credentials:&#xA;  Username: administrator&#xA;  Password: Admin2024!Secure&#xA;  Email: admin@example.com&#xA;&#xA;API Keys:&#xA;  Stripe Secret: sk_live_FAKE123456789abcdef&#xA;  AWS Access: AKIAIOSFODNN7EXAMPLE&#xA;  AWS Secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY&#xA;  SendGrid: SG.FAKE_SENDGRID_KEY_123456&#xA;&#xA;Server Info:&#xA;  IP: 192.168.1.100&#xA;  PHP: 8.2.0&#xA;  MySQL: 8.0.35&#xA;  WordPress: 6.4.2&#xA;                &amp;lt;/pre&amp;gt;&#xA;            &amp;lt;/div&amp;gt;&#xA;        &amp;lt;/div&amp;gt;&#xA;&#xA;        &amp;lt;div class=&amp;quot;widget&amp;quot;&amp;gt;&#xA;            &amp;lt;h3&amp;gt;Recent Activity&amp;lt;/h3&amp;gt;&#xA;            &amp;lt;ul&amp;gt;&#xA;                &amp;lt;li&amp;gt;Admin login from 192.168.1.50&amp;lt;/li&amp;gt;&#xA;                &amp;lt;li&amp;gt;Database backup completed&amp;lt;/li&amp;gt;&#xA;                &amp;lt;li&amp;gt;Plugin updated: WP Super Cache&amp;lt;/li&amp;gt;&#xA;                &amp;lt;li&amp;gt;New user registered: testuser&amp;lt;/li&amp;gt;&#xA;            &amp;lt;/ul&amp;gt;&#xA;        &amp;lt;/div&amp;gt;&#xA;    &amp;lt;/div&amp;gt;&#xA;&#xA;    &amp;lt;script&amp;gt;&#xA;        // CPU tarpit for bots&#xA;        console.log(&amp;quot;Loading WordPress admin dashboard...&amp;quot;);&#xA;&#xA;        let data = &amp;quot;&amp;quot;;&#xA;        for (let i = 0; i &amp;lt; 75_000_000; i++) {&#xA;            data += Math.random().toString(36);&#xA;            if (i % 5000000 === 0) {&#xA;                console.log(&amp;quot;Loading dashboard widgets... &amp;quot; + Math.floor(i / 750000) + &amp;quot;%&amp;quot;);&#xA;            }&#xA;        }&#xA;&#xA;        // Fake AJAX calls that waste more resources&#xA;        function fakeAjaxCall() {&#xA;            fetch(&#39;/wp-admin/admin-ajax.php?action=get_stats&#39;)&#xA;                .then(response =&amp;gt; response.json())&#xA;                .catch(err =&amp;gt; console.log(&#39;Loading...&#39;));&#xA;        }&#xA;&#xA;        setInterval(fakeAjaxCall, 100);&#xA;&#xA;        console.log(&amp;quot;Dashboard loaded. Data size: &amp;quot; + data.length + &amp;quot; bytes&amp;quot;);&#xA;    &amp;lt;/script&amp;gt;&#xA;&amp;lt;/body&amp;gt;&#xA;&amp;lt;/html&amp;gt;&#xA;&#xA;&amp;gt;&amp;gt;&amp;gt;&amp;gt; wp-admin/install.php&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;&amp;lt;?php&#xA;/**&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA; * WordPress Installation Script&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA; * Version: 6.4.2&#xA; *&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA; * WARNING: This file should be deleted after installation!&#xA; */&#xA;&#xA;// Fake WordPress installation page&#xA;?&amp;gt;&#xA;&amp;lt;!DOCTYPE html&amp;gt;&#xA;&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&#xA;&amp;lt;head&amp;gt;&#xA;    &amp;lt;meta charset=&amp;quot;UTF-8&amp;quot;&amp;gt;&#xA;    &amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1.0&amp;quot;&amp;gt;&#xA;    &amp;lt;meta name=&amp;quot;robots&amp;quot; content=&amp;quot;noindex, nofollow&amp;quot;&amp;gt;&#xA;    &amp;lt;title&amp;gt;WordPress Installation&amp;lt;/title&amp;gt;&#xA;    &amp;lt;style&amp;gt;&#xA;        body {&#xA;            font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Oxygen-Sans, Ubuntu, Cantarell, &amp;quot;Helvetica Neue&amp;quot;, sans-serif;&#xA;            background: #f1f1f1;&#xA;            margin: 0;&#xA;            padding: 20px;&#xA;        }&#xA;        .container {&#xA;            max-width: 600px;&#xA;            margin: 50px auto;&#xA;            background: white;&#xA;            padding: 30px;&#xA;            border-radius: 8px;&#xA;            box-shadow: 0 1px 3px rgba(0,0,0,0.13);&#xA;        }&#xA;        h1 { color: #23282d; }&#xA;        .form-group { margin-bottom: 20px; }&#xA;        label { display: block; margin-bottom: 5px; font-weight: 600; }&#xA;        input[type=&amp;quot;text&amp;quot;], input[type=&amp;quot;password&amp;quot;] {&#xA;            width: 100%;&#xA;            padding: 10px;&#xA;            border: 1px solid #ddd;&#xA;            border-radius: 4px;&#xA;            box-sizing: border-box;&#xA;        }&#xA;        .btn {&#xA;            background: #2271b1;&#xA;            color: white;&#xA;            padding: 12px 24px;&#xA;            border: none;&#xA;            border-radius: 4px;&#xA;            cursor: pointer;&#xA;            font-size: 14px;&#xA;        }&#xA;        .warning {&#xA;            background: #fcf8e3;&#xA;            border: 1px solid #faebcc;&#xA;            color: #8a6d3b;&#xA;            padding: 15px;&#xA;            border-radius: 4px;&#xA;            margin-bottom: 20px;&#xA;        }&#xA;    &amp;lt;/style&amp;gt;&#xA;&amp;lt;/head&amp;gt;&#xA;&amp;lt;body&amp;gt;&#xA;    &amp;lt;div class=&amp;quot;container&amp;quot;&amp;gt;&#xA;        &amp;lt;h1&amp;gt;WordPress Installation&amp;lt;/h1&amp;gt;&#xA;&#xA;        &amp;lt;div class=&amp;quot;warning&amp;quot;&amp;gt;&#xA;            &amp;lt;strong&amp;gt;Warning:&amp;lt;/strong&amp;gt; This installation script is publicly accessible.&#xA;            Please secure your site after installation.&#xA;        &amp;lt;/div&amp;gt;&#xA;&#xA;        &amp;lt;form method=&amp;quot;post&amp;quot; action=&amp;quot;install.php&amp;quot;&amp;gt;&#xA;            &amp;lt;div class=&amp;quot;form-group&amp;quot;&amp;gt;&#xA;                &amp;lt;label for=&amp;quot;db_name&amp;quot;&amp;gt;Database Name&amp;lt;/label&amp;gt;&#xA;                &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;db_name&amp;quot; name=&amp;quot;db_name&amp;quot; value=&amp;quot;wordpress_db&amp;quot; required&amp;gt;&#xA;            &amp;lt;/div&amp;gt;&#xA;&#xA;            &amp;lt;div class=&amp;quot;form-group&amp;quot;&amp;gt;&#xA;                &amp;lt;label for=&amp;quot;db_user&amp;quot;&amp;gt;Database Username&amp;lt;/label&amp;gt;&#xA;                &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;db_user&amp;quot; name=&amp;quot;db_user&amp;quot; value=&amp;quot;wp_admin&amp;quot; required&amp;gt;&#xA;            &amp;lt;/div&amp;gt;&#xA;&#xA;            &amp;lt;div class=&amp;quot;form-group&amp;quot;&amp;gt;&#xA;                &amp;lt;label for=&amp;quot;db_pass&amp;quot;&amp;gt;Database Password&amp;lt;/label&amp;gt;&#xA;                &amp;lt;input type=&amp;quot;password&amp;quot; id=&amp;quot;db_pass&amp;quot; name=&amp;quot;db_pass&amp;quot; value=&amp;quot;MyS3cr3tP@ss!&amp;quot; required&amp;gt;&#xA;            &amp;lt;/div&amp;gt;&#xA;&#xA;            &amp;lt;div class=&amp;quot;form-group&amp;quot;&amp;gt;&#xA;                &amp;lt;label for=&amp;quot;db_host&amp;quot;&amp;gt;Database Host&amp;lt;/label&amp;gt;&#xA;                &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;db_host&amp;quot; name=&amp;quot;db_host&amp;quot; value=&amp;quot;localhost&amp;quot; required&amp;gt;&#xA;            &amp;lt;/div&amp;gt;&#xA;&#xA;            &amp;lt;div class=&amp;quot;form-group&amp;quot;&amp;gt;&#xA;                &amp;lt;label for=&amp;quot;admin_user&amp;quot;&amp;gt;Admin Username&amp;lt;/label&amp;gt;&#xA;                &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;admin_user&amp;quot; name=&amp;quot;admin_user&amp;quot; value=&amp;quot;admin&amp;quot; required&amp;gt;&#xA;            &amp;lt;/div&amp;gt;&#xA;&#xA;            &amp;lt;div class=&amp;quot;form-group&amp;quot;&amp;gt;&#xA;                &amp;lt;label for=&amp;quot;admin_pass&amp;quot;&amp;gt;Admin Password&amp;lt;/label&amp;gt;&#xA;                &amp;lt;input type=&amp;quot;password&amp;quot; id=&amp;quot;admin_pass&amp;quot; name=&amp;quot;admin_pass&amp;quot; value=&amp;quot;Admin2024!&amp;quot; required&amp;gt;&#xA;            &amp;lt;/div&amp;gt;&#xA;&#xA;            &amp;lt;div class=&amp;quot;form-group&amp;quot;&amp;gt;&#xA;                &amp;lt;label for=&amp;quot;admin_email&amp;quot;&amp;gt;Admin Email&amp;lt;/label&amp;gt;&#xA;                &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;admin_email&amp;quot; name=&amp;quot;admin_email&amp;quot; value=&amp;quot;admin@example.com&amp;quot; required&amp;gt;&#xA;            &amp;lt;/div&amp;gt;&#xA;&#xA;            &amp;lt;button type=&amp;quot;submit&amp;quot; class=&amp;quot;btn&amp;quot;&amp;gt;Install WordPress&amp;lt;/button&amp;gt;&#xA;        &amp;lt;/form&amp;gt;&#xA;    &amp;lt;/div&amp;gt;&#xA;&#xA;    &amp;lt;script&amp;gt;&#xA;        // CPU tarpit - infinite loop to waste bot resources&#xA;        console.log(&amp;quot;Initializing WordPress installation...&amp;quot;);&#xA;&#xA;        let wasteTime = &amp;quot;&amp;quot;;&#xA;        for (let i = 0; i &amp;lt; 100_000_000; i++) {&#xA;            wasteTime += Math.random().toString(36).substring(2, 15);&#xA;            if (i % 1000000 === 0) {&#xA;                console.log(&amp;quot;Processing installation step &amp;quot; + (i / 1000000) + &amp;quot; of 100...&amp;quot;);&#xA;            }&#xA;        }&#xA;&#xA;        // More CPU waste&#xA;        function fibonacci(n) {&#xA;            if (n &amp;lt;= 1) return n;&#xA;            return fibonacci(n - 1) + fibonacci(n - 2);&#xA;        }&#xA;&#xA;        console.log(&amp;quot;Calculating security checksums...&amp;quot;);&#xA;        for (let i = 0; i &amp;lt; 35; i++) {&#xA;            fibonacci(i);&#xA;        }&#xA;&#xA;        console.log(&amp;quot;Installation data: &amp;quot; + wasteTime.substring(0, 100));&#xA;    &amp;lt;/script&amp;gt;&#xA;&amp;lt;/body&amp;gt;&#xA;&amp;lt;/html&amp;gt;&#xA;&amp;gt;&amp;gt;&amp;gt;&amp;gt; wp-admin/readme.html&#xA;&#xA;&amp;lt;!--markata-attribution--&amp;gt;&#xA;WordPress 6.2 — Readme (Just kidding, it&#39;s all fake.)&#xA;&#xA;&amp;gt;&amp;gt;&amp;gt;&amp;gt; wp-login.php&#xA;&#xA;&amp;lt;!DOCTYPE html&amp;gt;&#xA;&amp;lt;html&amp;gt;&#xA;&amp;lt;head&amp;gt;&#xA;  &amp;lt;title&amp;gt;Login&amp;lt;/title&amp;gt;&#xA;  &amp;lt;meta name=&amp;quot;robots&amp;quot; content=&amp;quot;noindex&amp;quot;&amp;gt;&#xA;  &amp;lt;style&amp;gt;&#xA;    body { font-family: sans-serif; }&#xA;  &amp;lt;/style&amp;gt;&#xA;&amp;lt;/head&amp;gt;&#xA;&amp;lt;body&amp;gt;&#xA;&amp;lt;h1&amp;gt;Login&amp;lt;/h1&amp;gt;&#xA;&amp;lt;p&amp;gt;Loading…&amp;lt;/p&amp;gt;&#xA;&#xA;&amp;lt;script&amp;gt;&#xA;// JS tarpit: burns bot CPU&#xA;let s = &amp;quot;&amp;quot;;&#xA;for (let i = 0; i &amp;lt; 50_000_000; i++) {&#xA;  s += Math.random().toString(36).substring(2);&#xA;}&#xA;document.body.innerHTML += &amp;quot;&amp;lt;pre&amp;gt;&amp;quot; + s + &amp;quot;&amp;lt;/pre&amp;gt;&amp;quot;;&#xA;&amp;lt;/script&amp;gt;&#xA;&#xA;&amp;lt;/body&amp;gt;&#xA;&amp;lt;/html&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Check SWAP in htop</title>
    <id>https://pype.dev/check-swap-in-htop/</id>
    <updated>2025-11-15T06:52:14Z</updated>
    <published>2025-11-15T06:52:14Z</published>
    <link href="https://pype.dev/check-swap-in-htop/" rel="alternate" type="text/html"></link>
    <summary type="text">I struggle with maxxing swap on all my machines, I am sure it&#39;s a neovim config that I&#39;ve propagated everywhere and I&#39;m too lazy to figure it out. Instead I...</summary>
    <content type="html">&lt;p&gt;I struggle with maxxing swap on all my machines, I am sure it&amp;rsquo;s a neovim config&#xA;that I&amp;rsquo;ve propagated everywhere and I&amp;rsquo;m too lazy to figure it out. Instead I&#xA;just swapoff and swapon kind of often&amp;hellip; but this morning I had to know how to&#xA;see what&amp;rsquo;s using all that swap&amp;hellip;.&lt;/p&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20251115125424_a1ddbd7c.png&#34; alt=&#34;20251115125424_a1ddbd7c.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;The way to see SWAP usage by process in htop is:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;open htop&lt;/li&gt;&#xA;&lt;li&gt;Slam &lt;code&gt;F2&lt;/code&gt; (&lt;code&gt;f&lt;/code&gt; if you&amp;rsquo;re just in old school &lt;code&gt;top&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;see the screenshot, find M_SWAP&lt;/li&gt;&#xA;&lt;li&gt;move M_SWAP to &lt;code&gt;Active Columns&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20251115125603_5d4af687.png&#34; alt=&#34;20251115125603_5d4af687.png&#34;&gt;&#xA;&lt;figcaption&gt;&lt;p&gt;Credit to &lt;a href=&#34;https://superuser.com/questions/206424/whats-using-my-swap-ubuntu&#34;&gt;this superuser post&lt;/a&gt;&lt;/p&gt;&lt;/figcaption&gt;&lt;/figure&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Speakr For Recording and Transcribing at Home</title>
    <id>https://pype.dev/speakr-for-recording-and-transcribing-at-home/</id>
    <updated>2025-11-11T05:02:37Z</updated>
    <published>2025-11-11T05:02:37Z</published>
    <link href="https://pype.dev/speakr-for-recording-and-transcribing-at-home/" rel="alternate" type="text/html"></link>
    <summary type="text">I have been using Whisper-WebUI for several months in my homelab to record and transcribe myself thinking out loud. It&#39;s been great. Then I came across...</summary>
    <content type="html">&lt;p&gt;I have been using Whisper-WebUI for several months in my homelab to record and&#xA;transcribe myself thinking out loud. It&amp;rsquo;s been great. Then I came across&#xA;&lt;a href=&#34;https://github.com/murtaza-nasir/speakr&#34;&gt;speakr&lt;/a&gt; which is like that but more&#xA;feature rich in what I wanted out of the WebUI. Specifically I get a nicer UI&#xA;with transcriptions, a chat window, built-in summarization, and diarization&#xA;support (WebUI has this too but it&amp;rsquo;s a little nicer in Speakr in my opinion).&lt;/p&gt;&#xA;&lt;h2 id=&#34;pic&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Pic&lt;/span&gt; &lt;a href=&#34;#pic&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250824120404_da722d66.png&#34; alt=&#34;20250824120404_da722d66.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;The UI is a little busy but handy for what I&amp;rsquo;m after in the mornings or when&#xA;I&amp;rsquo;m trying to mind-dump somewhere I can conveniently explore later.&lt;/p&gt;&#xA;&lt;h2 id=&#34;speaker-identification&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Speaker Identification&lt;/span&gt; &lt;a href=&#34;#speaker-identification&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Requires HuggingFace Token to pull the models that perform &lt;a href=&#34;https://en.wikipedia.org/wiki/Speaker_diarisation&#34;&gt;Speaker&#xA;diarisation&lt;/a&gt; - ie.&#xA;identifying different speakers&lt;/p&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s an example from an episode of Hybrid Cloud Show.&lt;/p&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250826124040_48c8d2ce.png&#34; alt=&#34;20250826124040_48c8d2ce.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>RepoFlow Robot User</title>
    <id>https://pype.dev/repoflow-robot-user/</id>
    <updated>2025-11-10T09:24:25Z</updated>
    <published>2025-11-10T09:24:25Z</published>
    <link href="https://pype.dev/repoflow-robot-user/" rel="alternate" type="text/html"></link>
    <summary type="text">I&#39;m trying to lean into repoFlow at home, and model some slightly better patterns than open borders to artifacts across all my services. As I&#39;m getting...</summary>
    <content type="html">&lt;p&gt;I&amp;rsquo;m trying to lean into &lt;a href=&#34;https://repoflow.io&#34;&gt;repoFlow&lt;/a&gt; at home, and model some slightly better&#xA;patterns than open borders to artifacts across all my services. As I&amp;rsquo;m getting repoflow&#xA;going I see that I can make users in the console, but then I do have to invite&#xA;users to workspaces with a manually generate invite link.&lt;/p&gt;&#xA;&lt;p&gt;The workspaces an abstraction layer, and in each workspace can be many kinds of&#xA;repositories. For my purposes I&amp;rsquo;ll probably have 2 workspaces, even though 1&#xA;would almost certainly suffice.&lt;/p&gt;&#xA;&lt;p&gt;There doesn&amp;rsquo;t seem to be a way to add a user to a workspace from the admin&#xA;setting so for a while I was pretty confused why I couldn&amp;rsquo;t add my robot user&#xA;to a docker repository in my main workspace&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;After generating the invite link and accepting though then I see in the workspace settings a&#xA;simple click to give the robot user access to all repos (if you want)&lt;/p&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20251111122419_580b2ad4.png&#34; alt=&#34;20251111122419_580b2ad4.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20251110162252_6c7b2fe9.png&#34; alt=&#34;20251110162252_6c7b2fe9.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;&lt;code&gt;Can manage&lt;/code&gt; allows the user to mutate tags (ie. push &lt;code&gt;latest&lt;/code&gt; docker tags). If&#xA;the user only has &lt;code&gt;Can deploy&lt;/code&gt; then they can only create new artifacts (ie. not&#xA;mutate any tags)&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Use Jellyfin Tags For Content Moderation</title>
    <id>https://pype.dev/use-jellyfin-tags-for-content-moderation/</id>
    <updated>2025-10-08T10:21:01Z</updated>
    <published>2025-10-08T10:21:01Z</published>
    <link href="https://pype.dev/use-jellyfin-tags-for-content-moderation/" rel="alternate" type="text/html"></link>
    <summary type="text">Jellyfin brings in ratings and allows you to set custom ratings for shows, which is nice for things like &#34;block anything worse than TV-14 for my kid&#39;s...</summary>
    <content type="html">&lt;p&gt;Jellyfin brings in ratings and allows you to set custom ratings for shows,&#xA;which is nice for things like &amp;ldquo;block anything worse than TV-14 for my kid&amp;rsquo;s&#xA;account&amp;rdquo;. But what if my firend&amp;rsquo;s kids can watch shows I don&amp;rsquo;t want my kids&#xA;watching? Turns out tags exist and are great!&lt;/p&gt;&#xA;&lt;h2 id=&#34;tag-the-content&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Tag the content&lt;/span&gt; &lt;a href=&#34;#tag-the-content&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;First is to actually tag the content - in the UI it&amp;rsquo;s simple.&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Login with admin&lt;/li&gt;&#xA;&lt;li&gt;Manage Metadata&lt;/li&gt;&#xA;&lt;li&gt;Click the content you want to tag and find the &lt;code&gt;Tags&lt;/code&gt; section&lt;/li&gt;&#xA;&lt;li&gt;Add your tag&amp;hellip; for example &lt;code&gt;blocked:girls&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;filter-on-the-account&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Filter on the account&lt;/span&gt; &lt;a href=&#34;#filter-on-the-account&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Go to &lt;code&gt;Dashboard&lt;/code&gt; -&amp;gt; &lt;code&gt;Users&lt;/code&gt; -&amp;gt; &lt;code&gt;Library Access&lt;/code&gt; -&amp;gt; &lt;code&gt;Parental Control&lt;/code&gt; -&amp;gt; &lt;code&gt;Block items with tags&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Chili Notes</title>
    <id>https://pype.dev/chili-notes/</id>
    <updated>2025-10-04T13:42:09Z</updated>
    <published>2025-10-04T13:42:09Z</published>
    <link href="https://pype.dev/chili-notes/" rel="alternate" type="text/html"></link>
    <summary type="text">I could&#39;ve sworn I had a chili list going but alas...</summary>
    <content type="html">&lt;p&gt;I could&amp;rsquo;ve sworn I had a chili list going but alas&amp;hellip;&lt;/p&gt;&#xA;&lt;h1 id=&#34;2025-10-04&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;2025-10-04&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;2 lbs ground beef&#xA;1 big can of pinto beans&#xA;3 small cans of black beans&#xA;3 cans diced tomatoes&#xA;2 onions diced&lt;/p&gt;&#xA;&lt;p&gt;This is last minute chili for church pot-luck&amp;hellip; poor planning&lt;/p&gt;&#xA;&lt;p&gt;I browned the meat and seasoned similar to how I might for tacos, but lighter on cumin and added chili powder.&lt;/p&gt;&#xA;&lt;p&gt;Dumped the browned meant, tomtoes, and beans into crock pot. Seasoned with a healthy amount of garlic powder, chili powder, cumin, and salt.&#xA;Browned the onions, and dumped in.&#xA;Let stew for a few hours.&#xA;Eat.&lt;/p&gt;&#xA;&lt;h2 id=&#34;review&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Review&lt;/span&gt; &lt;a href=&#34;#review&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;1 bowl was great. The yellow onion still seem to add a little bit of heat, maybe could&amp;rsquo;ve sauteed them longer&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Sending SMS with SMTP</title>
    <id>https://pype.dev/sending-sms-with-smtp/</id>
    <updated>2025-10-04T09:38:58Z</updated>
    <published>2025-10-04T09:38:58Z</published>
    <link href="https://pype.dev/sending-sms-with-smtp/" rel="alternate" type="text/html"></link>
    <summary type="text">I&#39;m cooking something up over here that will include SMS message notifications as a feature and I&#39;ve been doing some reading on different providers...</summary>
    <content type="html">&lt;p&gt;I&amp;rsquo;m cooking something up over here that will include SMS message notifications&#xA;as a feature and I&amp;rsquo;ve been doing some reading on different providers&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;Many specialize in bulk SMS messaging, like for campaigns and promotions. So&#xA;this pricing model doesn&amp;rsquo;t work for me.&lt;/p&gt;&#xA;&lt;p&gt;The providers that do quick single SMS messages are often $0.005 to $.04 cents&#xA;per message which isn&amp;rsquo;t insanity but I&amp;rsquo;m not exactly backed by anyone&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;Well today I learned that you can actually send SMS messages via SMTP! I&#xA;wouldn&amp;rsquo;t bank on total reliability here but for testing and initial roll out of&#xA;what I want I think this will be perfect.&lt;/p&gt;&#xA;&lt;p&gt;And because I&amp;rsquo;m just that kind of guy, here&amp;rsquo;s some code you can &lt;code&gt;uv run smtp2sms.py&lt;/code&gt; and get yourself a handy little text. I&amp;rsquo;m going to build a simpler&#xA;module but you can get a &lt;code&gt;gmail&lt;/code&gt; and &lt;code&gt;gmail app password&lt;/code&gt; within about 10&#xA;minutes. &lt;a href=&#34;https://support.google.com/mail/answer/185833?hl=en&#34;&gt;see here&lt;/a&gt;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# /// script&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# requires-python = &amp;#34;&amp;gt;=3.10&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# dependencies = [&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# ]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# ///&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;smtplib&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;email.mime.text&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;MIMEText&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;SMTP_APP_USER&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;environ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;SMTP_APP_USER&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;# me@gmail.com&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;SMTP_APP_PASSWORD&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;environ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;SMTP_APP_PASSWORD&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;SMTP_SERVER&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;environ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;SMTP_SERVER&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# smtp.gmail.ch&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# NOTE: I haven&amp;#39;t verified all the carrier domains - this was provided by ChatGPT&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;carriers&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;att&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;sms&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;txt.att.net&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;mms&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;mms.att.net&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;tmobile&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;sms&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;tmomail.net&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;mms&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;tmomail.net&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;verizon&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;# &amp;#34;sms&amp;#34;: &amp;#34;vtext.com&amp;#34;, # not reliable&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;sms&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;vzwpix.com&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;mms&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;vzwpix.com&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;sprint&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;sms&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;messaging.sprintpcs.com&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;mms&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;pm.sprint.com&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;googlefi&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;sms&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;msg.fi.google.com&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;mms&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;msg.fi.google.com&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;uscellular&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;sms&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;email.uscc.net&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;mms&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;mms.uscc.net&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;boost&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;sms&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;sms.myboostmobile.com&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;mms&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;myboostmobile.com&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;cricket&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;sms&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;sms.cricketwireless.net&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;mms&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;mms.cricketwireless.net&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;metropcs&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;sms&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;mymetropcs.com&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;mms&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;mymetropcs.com&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;virgin&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;sms&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;vmobl.com&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;mms&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;vmobl.com&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;contacts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;me&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;carrier&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;verizon&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;number&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;1234567890&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;msg&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;MIMEText&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Hello from a python script? What?!&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;msg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;From&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SMTP_APP_USER&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;SEND_TO&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;me&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Complex for my future use cases - deal with it&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;msg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;To&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;contacts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SEND_TO&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;number&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;carriers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;contacts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SEND_TO&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;carrier&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]][&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;sms&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;with&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;smtplib&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SMTP&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SMTP_SERVER&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;587&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;email_handler&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;email_handler&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;starttls&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;email_handler&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;login&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SMTP_APP_USER&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SMTP_APP_PASSWORD&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;email_handler&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sendmail&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SMTP_APP_USER&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;msg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;To&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]],&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;msg&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;as_string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Docker Compose Build From Git Repo</title>
    <id>https://pype.dev/docker-compose-build-from-git-repo/</id>
    <updated>2025-09-12T08:45:20Z</updated>
    <published>2025-09-12T08:45:20Z</published>
    <link href="https://pype.dev/docker-compose-build-from-git-repo/" rel="alternate" type="text/html"></link>
    <summary type="text">You can reference a git repo in compose&#39;s &#34;build&#34; argument for a service as of this PR</summary>
    <content type="html">&lt;p&gt;You can reference a git repo in compose&amp;rsquo;s &amp;ldquo;build&amp;rdquo; argument for a service as of &lt;a href=&#34;https://github.com/docker/compose/pull/2430&#34;&gt;this PR&lt;/a&gt;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>💭 uv script management</title>
    <id>https://pype.dev/thoughts-831/</id>
    <updated>2025-09-08T11:25:33Z</updated>
    <published>2025-09-08T11:25:33Z</published>
    <link href="https://pype.dev/thoughts-831/" rel="alternate" type="text/html"></link>
    <summary type="text">Dang Waylon! Love these few lines... uv is great, been using it for environment and project requirements management bu</summary>
    <content type="text">&#xA;&lt;a href=&#34;https://waylonwalker.com/uv-script-management/##sed+-i+&#39;1i+#!/usr/bin/env+-S+uv+run+--script&#39;+up&#34;&gt;&#xA;    &lt;img&#xA;        src=&#34;https://shots.wayl.one/shot/?url=https://waylonwalker.com/uv-script-management/##sed+-i+&#39;1i+#!/usr/bin/env+-S+uv+run+--script&#39;+up&amp;height=450&amp;width=800&amp;scaled_width=800&amp;scaled_height=450&amp;selectors=&#34;&#xA;        alt=&#34;shot of post - uv script management&#34;&#xA;        height=450&#xA;        width=800&#xA;    &gt;&#xA;&lt;/a&gt;&#xA;&#xA;Here&#39;s my thought on &lt;a href=&#34;https://waylonwalker.com/uv-script-management/##sed+-i+&#39;1i+#!/usr/bin/env+-S+uv+run+--script&#39;+up&#34;&gt;uv script management&lt;/a&gt;&#xA;&#xA;---&#xA;&#xA;Dang Waylon! Love these few lines... `uv` is great, been using it for environment and project requirements management but I didn&#39;t realize it was this easy to setup a pep 723 compliant script!&#xA;&#xA;Love this `sed -i &#39;1i #!/usr/bin/env -S uv run --script&#39;` little gem too - I typically do `uv run script.py` so I&#39;ll see about making this a simple zsh alias for faster iteration on python scripts... I often have AI write quick bash scripts to accomplish things, but it&#39;s quite a bit harder for me to read than python, and with the power `uv` is bringing to the python ecosystem, maybe it&#39;s fine to just be a little higher in the programming stack for script-kitty stuff&#xA;&#xA;---&#xA;&#xA;!!! note&#xA;    This is one of [[ my-thoughts ]]. I picked this up from [Waylon Walker](https://waylonwalker.com)(https://thoughts.waylonwalker.com). It&#39;s a short note that I make about someone else&#39;s content online.  Learn more about the process [[ thoughts ]]&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Zsh alias for uv scripts</title>
    <id>https://pype.dev/zsh-alias-for-uv-scripts/</id>
    <updated>2025-09-08T06:33:13Z</updated>
    <published>2025-09-08T06:33:13Z</published>
    <link href="https://pype.dev/zsh-alias-for-uv-scripts/" rel="alternate" type="text/html"></link>
    <summary type="text">It&#39;s apparently advantageous for uv to have a specific shebang set that doesn&#39;t add, no problem, we can have a zsh alias for it</summary>
    <content type="html">&lt;p&gt;It&amp;rsquo;s apparently advantageous for uv to have a specific shebang set that &lt;code&gt;uv init&lt;/code&gt; doesn&amp;rsquo;t add, no problem, we can have a zsh alias for it&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;alias&lt;/span&gt; add-shebang&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;f(){ &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;  if [[ ! -s $1 ]]; then &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;    echo &amp;#34;#!/usr/bin/env -S uv run --script&amp;#34; &amp;gt; &amp;#34;$1&amp;#34;; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;  elif head -n1 &amp;#34;$1&amp;#34; | grep -q &amp;#34;^#!&amp;#34;; then &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;    echo &amp;#34;Shebang already present in $1&amp;#34;; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;  else &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;    sed -i &amp;#34;1i #!/usr/bin/env -S uv run --script&amp;#34; &amp;#34;$1&amp;#34;; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;  fi&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;}; f&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then if you have a python script from &lt;code&gt;uv init --script&lt;/code&gt; you can &lt;code&gt;add-shebang myscript.py&lt;/code&gt; to add the shebang.&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Reflection - AI Work and ADHD</title>
    <id>https://pype.dev/reflection-ai-work-and-adhd/</id>
    <updated>2025-08-27T07:16:57Z</updated>
    <published>2025-08-27T07:16:57Z</published>
    <link href="https://pype.dev/reflection-ai-work-and-adhd/" rel="alternate" type="text/html"></link>
    <summary type="text">It&#39;s time to be more devoted to my work... AI has been a cool technology to watch and experience but one thing I&#39;m allowing it to do to me is to kill my love...</summary>
    <content type="html">&lt;h2 id=&#34;reflection&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Reflection&lt;/span&gt; &lt;a href=&#34;#reflection&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;It&amp;rsquo;s time to be more devoted to my work&amp;hellip; AI has been a cool technology to&#xA;watch and experience but one thing I&amp;rsquo;m allowing it to do to me is to kill my love for&#xA;building&amp;hellip; I feel like I&amp;rsquo;m arriving where I&amp;rsquo;ve already seen many talented&#xA;developers get to -&lt;/p&gt;&#xA;&lt;div class=&#34;admonition danger&#34;&gt;&#xA;&lt;p class=&#34;admonition-title&#34;&gt;realization&lt;/p&gt;&#xA;&lt;p&gt;AI is not magic, it&amp;rsquo;s a headache.&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;Don&amp;rsquo;t get me wrong, targeted and focused use of LLMs, with careful planning and&#xA;time-boxing can be great, and has been for me. But I am a creature and prone to&#xA;take the path of least resistance, and in many cases I&amp;rsquo;m just letting the LLM&#xA;do the work. This is where the ADHD element from the title comes into play.&#xA;Now, I&amp;rsquo;m not blaming ADHD for me being lazy, because I&amp;rsquo;m not sure laziness is&#xA;the fairest descriptor of where I&amp;rsquo;ve been lately. A common issue for those with&#xA;ADHD, maybe even the defining characteristic, is the black-hole that&amp;rsquo;s present in the space&#xA;where motiviation and reward belong in the brain. I&amp;rsquo;ve resonated with this thought for much of my life:&lt;/p&gt;&#xA;&lt;div class=&#34;admonition note&#34;&gt;&#xA;&lt;p class=&#34;admonition-title&#34;&gt;Fulfilled or Relieved&lt;/p&gt;&#xA;&lt;p&gt;When I finish tasks, I&amp;rsquo;m not fulfilled&amp;hellip; if anything I&amp;rsquo;m relieved.&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;This is a core issue I am seeking to address in my life, and I guess in&#xA;real-time reflection I should thank the hellscape of AI and LLMs for surfacing&#xA;this pattern in my make-up today instead of when I&amp;rsquo;m in my 40s or 50s.&lt;/p&gt;&#xA;&lt;p&gt;So where I&amp;rsquo;ve been is that I&amp;rsquo;ll let an LLM write code and then I&amp;rsquo;ll attempt to&#xA;be validating the tests or example scripts I prompt it to generate, get&#xA;comfortable with it, and ship.&lt;/p&gt;&#xA;&lt;p&gt;But then in a few weeks the context of that code is all&#xA;lost on me&amp;hellip; I didn&amp;rsquo;t craft it with blood and sweat and so when I&amp;rsquo;m asked a&#xA;question about it I realize I&amp;rsquo;m barely fluent in a thing I built (did I even build it?)!&lt;/p&gt;&#xA;&lt;p&gt;This is embarrassing and exhausting&amp;hellip; I&amp;rsquo;m not sure what I&amp;rsquo;m gonna do about&#xA;this, definitely not write about how I&amp;rsquo;m going to change my life over this&#xA;dissastisfaction and from this day forward everything will be different&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;But today does feel like an infelction point in a trajectory I&amp;rsquo;ve been on with&#xA;AI and my job, so not starting today, but just a decision I am making today, is&#xA;to time-box every task with vigorous commitment.&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Pair AceGamer Wireless PS4 Controller With PC</title>
    <id>https://pype.dev/pair-acegamer-wireless-ps4-controller-with-pc/</id>
    <updated>2025-08-14T06:51:12Z</updated>
    <published>2025-08-14T06:51:12Z</published>
    <link href="https://pype.dev/pair-acegamer-wireless-ps4-controller-with-pc/" rel="alternate" type="text/html"></link>
    <summary type="text">I bought a $20 PS4 knock-off controller recently as my PS4 controllers are 12 years old (to me!) and I bought them used before that... the instructions for a...</summary>
    <content type="html">&lt;p&gt;I bought a $20 PS4 knock-off controller recently as my PS4 controllers are 12&#xA;years old (to me!) and I bought them used before that&amp;hellip; the instructions for a&#xA;$20 controller are obviously bad but a godsend redittor discovered the hidden&#xA;secret to pair this device with my computer! Instructions (for ps4) say to plug&#xA;it in, hit the home button, and you&amp;rsquo;re paired. Now, that didn&amp;rsquo;t work on PC&#xA;obviously, but it ALSO didn&amp;rsquo;t work on my PS4&amp;hellip; Unfortunte! It works wired just&#xA;fine, but turns out the magic to send the thing into traditional Bluetooth&#xA;Pairing Mode is to hold the home and share buttons down - wait for a rapid few&#xA;blinks - then you&amp;rsquo;ll see the controller in your bluetooth pairing menu!&lt;/p&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250814115137_34c132cd.png&#34; alt=&#34;20250814115137_34c132cd.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Proxy Pull Docker Images From Self-Hosted Container Registry Through Self-Hosted Repoflow</title>
    <id>https://pype.dev/proxy-pull-docker-images-from-self-hosted-container-registry-through-self-hosted-repoflow/</id>
    <updated>2025-08-12T06:59:02Z</updated>
    <published>2025-08-12T06:59:02Z</published>
    <link href="https://pype.dev/proxy-pull-docker-images-from-self-hosted-container-registry-through-self-hosted-repoflow/" rel="alternate" type="text/html"></link>
    <summary type="text">This post is a short write-up of an issue I had while exploring Reploflow - a super solid artifactory-esq replacement for the homelab (and enterprise!). I&#39;ve...</summary>
    <content type="html">&lt;p&gt;This post is a short write-up of an issue I had while exploring &lt;a href=&#34;https://repoflow.io&#34;&gt;Reploflow&lt;/a&gt; - a&#xA;super solid artifactory-esq replacement for the homelab (and enterprise!). I&amp;rsquo;ve been playing with&#xA;it and have tried to setup a few artifact repos that I&amp;rsquo;m familiar with - docker&#xA;and pypi.&lt;/p&gt;&#xA;&lt;h2 id=&#34;pypi&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;PyPi&lt;/span&gt; &lt;a href=&#34;#pypi&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;This isn&amp;rsquo;t a post about repoflow, but I had an issue with pypi and Tomer was&#xA;EXTREMELY responsive in helping to fix my issue and patch repoflow within a day&#xA;of me reporting the issue via email!&lt;/p&gt;&#xA;&lt;h2 id=&#34;docker&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Docker&lt;/span&gt; &lt;a href=&#34;#docker&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;For docker I have a few options I just wanted to see work - obviously&#xA;proxy pull from Dockerhub for ease, but also in the interim I&amp;rsquo;d like to proxy&#xA;pull from my original container registry to avoid having to update any homelab config just yet.&#xA;Now, obviously I&amp;rsquo;ll have to update all my build pipelines to start using&#xA;repoflow, and my homelab configuration to reference the repoflow docker&#xA;repository rather than my existing registry.&lt;/p&gt;&#xA;&lt;p&gt;But there&amp;rsquo;s something to bear in mind if maintaining that middle registry -&#xA;turns out a there&amp;rsquo;s a default namespace in dockerhub &lt;code&gt;/library/&lt;/code&gt; and repoflow&#xA;expects this standard across any docker registry, so it&amp;rsquo;s pull paths fully&#xA;resolve to an incorrect tag if you don&amp;rsquo;t take this into account in your&#xA;existing infrastructure.&lt;/p&gt;&#xA;&lt;p&gt;TLDR: if you tag an image &lt;code&gt;myregistry/ubuntu:latest&lt;/code&gt; and push it&#xA;then try to pull it back through repoflow then repoflow expects the image to be&#xA;&lt;code&gt;myregistry/library/ubuntu:latest&lt;/code&gt;. I think repoflow should support&#xA;configurating the namespace/org for the images - but in the meantime I can&#xA;go find all my images and update my build scripts to add /library/ to my&#xA;tags&amp;hellip; or while I&amp;rsquo;m doing that I can just push to repoflow directly&amp;hellip; All in&#xA;all, nice little lesson on namespaces in docker repos and third-party tooling.&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>A Simple Lua Plugin To Find My Drafts</title>
    <id>https://pype.dev/a-simple-lua-plugin-to-find-my-drafts/</id>
    <updated>2025-08-10T20:56:33Z</updated>
    <published>2025-08-10T20:56:33Z</published>
    <link href="https://pype.dev/a-simple-lua-plugin-to-find-my-drafts/" rel="alternate" type="text/html"></link>
    <summary type="text">I used windsurf to write daily-notes-neovim-plugin for navigating my daily notes in neovim.</summary>
    <content type="text">&#xA;I used windsurf to write [[daily-notes-neovim-plugin]] for navigating my daily notes in neovim.&#xA;&#xA;For a while now I&#39;ve wanted a way to see my blog drafts... and tonight finally got the massive courage to prompt gpt-5 to build it for me...&#xA;&#xA;## Screenshot&#xA;&#xA;&#xA;![20250811020234_e0c02600.png](https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250811020234_e0c02600.png)&#xA;&#xA;## Code&#xA;&#xA;```lua&#xA;---@diagnostic disable: undefined-global&#xA;-- Blogging plugin: find draft blog posts under `pages/`&#xA;-- Draft = YAML front matter contains `published: false` (case-insensitive)&#xA;&#xA;local M = {}&#xA;&#xA;-- Read file and return YAML front matter block as string, or nil&#xA;local function read_front_matter(path)&#xA;  local fh = io.open(path, &#34;r&#34;)&#xA;  if not fh then&#xA;    return nil&#xA;  end&#xA;  local content = fh:read(&#34;*a&#34;)&#xA;  fh:close()&#xA;  if not content then&#xA;    return nil&#xA;  end&#xA;&#xA;  -- Front matter starts with --- on first line and ends with --- on its own line&#xA;  -- Support optional CRLF&#xA;  local start_s, start_e = content:find(&#34;^%-%-%-%s*\r?\n&#34;)&#xA;  if not start_e then&#xA;    return nil&#xA;  end&#xA;  local fm_end_s, fm_end_e = content:find(&#34;\n%-%-%-%s*\r?\n&#34;, start_e + 1)&#xA;  if not fm_end_s then&#xA;    return nil&#xA;  end&#xA;  -- Extract between the fence lines (exclude the starting and ending --- lines)&#xA;  local front_matter = content:sub(start_e + 1, fm_end_s)&#xA;  return front_matter&#xA;end&#xA;&#xA;-- Determine if a file is a draft by inspecting front matter for published: false&#xA;function M._is_draft(path)&#xA;  local fm = read_front_matter(path)&#xA;  if not fm then&#xA;    return false&#xA;  end&#xA;  -- Find a line starting with `published:` and capture the value&#xA;  -- Trim comments and quotes, compare case-insensitively&#xA;  local value = fm:match(&#34;[Pp][Uu][Bb][Ll][Ii][Ss][Hh][Ee][Dd]%s*:%s*([^\n\r]+)&#34;)&#xA;  if not value then&#xA;    return false&#xA;  end&#xA;  -- strip inline comments starting with # and surrounding quotes/space&#xA;  value = value:gsub(&#34;#.*$&#34;, &#34;&#34;)&#xA;  value = value:gsub(&#39;&#34;&#39;, &#34;&#34;):gsub(&#34;&#39;&#34;, &#34;&#34;)&#xA;  value = value:gsub(&#34;^%s+&#34;, &#34;&#34;):gsub(&#34;%s+$&#34;, &#34;&#34;)&#xA;  local v = value:lower()&#xA;  if v == &#34;false&#34; or v == &#34;no&#34; or v == &#34;0&#34; then&#xA;    return true&#xA;  end&#xA;  return false&#xA;end&#xA;&#xA;-- Telescope picker for draft posts&#xA;function M.find_drafts()&#xA;  local ok_pickers, pickers = pcall(require, &#34;telescope.pickers&#34;)&#xA;  if not ok_pickers then&#xA;    vim.notify(&#34;telescope.nvim not available&#34;, vim.log.levels.ERROR)&#xA;    return&#xA;  end&#xA;  local finders = require(&#34;telescope.finders&#34;)&#xA;  local previewers = require(&#34;telescope.previewers&#34;)&#xA;  local conf = require(&#34;telescope.config&#34;).values&#xA;  local actions = require(&#34;telescope.actions&#34;)&#xA;  local action_state = require(&#34;telescope.actions.state&#34;)&#xA;&#xA;  -- Collect markdown files under pages/&#xA;  local files = vim.fn.glob(&#34;pages/**/*.md&#34;, false, true)&#xA;  local drafts = {}&#xA;  for _, f in ipairs(files) do&#xA;    if M._is_draft(f) then&#xA;      table.insert(drafts, f)&#xA;    end&#xA;  end&#xA;&#xA;  if #drafts == 0 then&#xA;    vim.notify(&#34;No draft blog posts found in pages/&#34;, vim.log.levels.INFO)&#xA;    return&#xA;  end&#xA;&#xA;  -- Simple, version-agnostic entry maker&#xA;  local function entry_maker_fn(line)&#xA;    return {&#xA;      value = line,&#xA;      ordinal = line,&#xA;      display = vim.fn.fnamemodify(line, &#34;:~:.&#34;) or line,&#xA;      path = line,&#xA;    }&#xA;  end&#xA;&#xA;  -- Use Telescope builtin find_files with a custom command that lists only drafts.&#xA;  -- This guarantees previews and matches the style of other file pickers.&#xA;  local tmpfile = vim.fn.tempname()&#xA;  local ok_write, err = pcall(function()&#xA;    local fh = assert(io.open(tmpfile, &#34;w&#34;))&#xA;    for _, f in ipairs(drafts) do&#xA;      fh:write(f .. &#34;\n&#34;)&#xA;    end&#xA;    fh:close()&#xA;  end)&#xA;  if not ok_write then&#xA;    vim.notify(&#34;Failed to prepare drafts list: &#34; .. tostring(err), vim.log.levels.ERROR)&#xA;    return&#xA;  end&#xA;&#xA;  local builtin = require(&#34;telescope.builtin&#34;)&#xA;  builtin.find_files({&#xA;    prompt_title = &#34;Draft Blog Posts&#34;,&#xA;    -- cat the tmp list so Telescope treats it like find output&#xA;    find_command = { &#34;bash&#34;, &#34;-lc&#34;, string.format(&#39;cat %q&#39;, tmpfile) },&#xA;    attach_mappings = function(prompt_bufnr, map)&#xA;      local actions = require(&#34;telescope.actions&#34;)&#xA;      actions.close:enhance({&#xA;        post = function()&#xA;          os.remove(tmpfile)&#xA;        end,&#xA;      })&#xA;      return true&#xA;    end,&#xA;  })&#xA;end&#xA;&#xA;-- Expose a user command similar to daily plugin style&#xA;vim.api.nvim_create_user_command(&#34;BlogDrafts&#34;, function()&#xA;  M.find_drafts()&#xA;end, {})&#xA;&#xA;return M&#xA;&#xA;&#xA;```&#xA;&#xA;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>AudioMass</title>
    <id>https://pype.dev/audiomass/</id>
    <updated>2025-08-10T14:17:43Z</updated>
    <published>2025-08-10T14:17:43Z</published>
    <link href="https://pype.dev/audiomass/" rel="alternate" type="text/html"></link>
    <summary type="text">I edit our church&#39;s recorded sermons every week and upload them to our website. It&#39;s very simple, and the editing is just cutting the audio file down on the...</summary>
    <content type="html">&lt;p&gt;I edit our church&amp;rsquo;s recorded sermons every week and upload them to our website.&#xA;It&amp;rsquo;s very simple, and the editing is just cutting the audio file down on the&#xA;front and back sides of extra stuff picked up while the mic was on. I&amp;rsquo;ve been&#xA;doing this for a while using Davinci Resolve which is WAY too heavy for&#xA;trimming audio files but I&amp;rsquo;m loosely familiar with it and so I just have been&#xA;dealing with the pain of long start up, overly complicated organization, etc.&#xA;Well it&amp;rsquo;s been buggy on Aurora for me and a few weeks ago I got sick of it&#xA;finally and tried KdenLive&amp;hellip;. Now this is a great tool, but again I&amp;rsquo;m just&#xA;cutting up some audio files, why is this hard?&lt;/p&gt;&#xA;&lt;p&gt;Double finally I just did some research and after a few minutes found&#xA;&lt;a href=&#34;https://github.com/pkalogiros/AudioMass&#34;&gt;audiomass&lt;/a&gt; which I immediately forked&#xA;and dockerized cause it&amp;rsquo;s so simple and beautiful!&lt;/p&gt;&#xA;&lt;p&gt;Now I have a little webapp to trim these files from - almost such that the tech&#xA;lead on Sunday could maybe do this instead of me!&lt;/p&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250810191909_cc0dc2d7.png&#34; alt=&#34;20250810191909_cc0dc2d7.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;You can check it out on &lt;a href=&#34;https://github.com/pypeaday/audiomass&#34;&gt;my github&lt;/a&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;clone&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;docker compose up -d&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;http://localhost:5056&lt;/code&gt; to begin trimming audio locally!&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Using Litestream to Restore My Database for Easy Development</title>
    <id>https://pype.dev/using-litestream-to-restore-my-database-for-easy-development/</id>
    <updated>2025-08-07T15:14:45Z</updated>
    <published>2025-08-07T15:14:45Z</published>
    <link href="https://pype.dev/using-litestream-to-restore-my-database-for-easy-development/" rel="alternate" type="text/html"></link>
    <summary type="text">see using-litestream-to-backup-quadtasks-sqlite-db for how I setup litestream replication for quadtask</summary>
    <content type="text">&#xA;# Litestream&#xA;&#xA;see [[using-litestream-to-backup-quadtasks-sqlite-db]] for how I setup litestream replication for [[quadtask]]&#xA;&#xA;I have the entrypoint to my app container check if the sqlite database exists&#xA;or not - in production or with local volume mounts, it will and then we start&#xA;litestream replication and then the app like normal. But what&#39;s awesome about&#xA;this little trick I got from [this litestream&#xA;example](https://github.com/benbjohnson/litestream-docker-example/tree/main) is&#xA;I can docker compose up locally without the data directory volume mounted in,&#xA;and get a fresh copy of my production data right there locally to work with!&#xA;&#xA;My entrypoint script now looks like:&#xA;&#xA;```bash&#xA;#!/bin/bash&#xA;&#xA;# Exit on error, undefined vars, and fail on pipe errors&#xA;set -euo pipefail&#xA;# Restore the database if it does not already exist.&#xA;if [ -f /app/data/quadtask.db ]; then&#xA; echo &#34;Database already exists, skipping restore&#34;&#xA;else&#xA; echo &#34;No database found, restoring from replica if exists&#34;&#xA; litestream restore -v /app/data/quadtask.db&#xA;fi&#xA;# Run litestream with your app as the subprocess.&#xA;exec litestream replicate -exec &#34;uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload --log-level debug&#34;&#xA;&#xA;```&#xA;&#xA;## Appropriate and Safe Replication&#xA;&#xA;The way to get prod data in automatically is to restore from the production&#xA;backup but I don&#39;t want to replicate to the production backup with my local&#xA;work, so it&#39;s not the best but I have a manual step that makes it pretty easy&#xA;&#xA;I first `just sync-db`&#xA;&#xA;```bash&#xA;# Sync production database locally&#xA;sync-db:&#xA;    fly ssh console -a quadtask -C &#39;cat /app/data/quadtask.db&#39; &gt; ./litestream/source/quadtask-prod.db&#xA;```&#xA;&#xA;and this brings my database down to a folder I maintain locally.&#xA;&#xA;I have litestream installed on my desktop obviously, and here&#39;s the relevant litestream configuration I use:&#xA;&#xA;```yaml&#xA;dbs:&#xA;  - path: /home/nic/projects/personal/quadtask/litestream/source/quadtask-prod.db&#xA;    replicas:&#xA;      - name: quadtask-prod&#xA;        type: s3&#xA;        bucket: litestream&#xA;        path: quadtask-local&#xA;        endpoint: s3.example.com&#xA;        skip-verify: false&#xA;        region: us-east-1&#xA;```&#xA;&#xA;So on my desktop if I `litestream replicate` then basically I&#39;m taking the&#xA;output of `just synd-db` and replicating to my litestream bucket to the&#xA;`quadtask-local` path.&#xA;&#xA;Then I start up my app, it restores from that point and I&#39;m working with fresh&#xA;prod data!&#xA;&#xA;## How To Handle Environments?&#xA;&#xA;I have this working for different environments too, with a little bit of&#xA;process but basically thanks to [litestream expanding env&#xA;vars](https://litestream.io/reference/config/#variable-expansion) in the config&#xA;we can do something like this:&#xA;&#xA;```yaml&#xA;dbs:&#xA;  - path: /app/data/quadtask.db&#xA;    replicas:&#xA;      - name: quadtask&#xA;        type: s3&#xA;        bucket: litestream&#xA;        path: quadtask-${ENVIRONMENT}&#xA;        endpoint: s3.example.com&#xA;        skip-verify: false&#xA;        region: us-east-1&#xA;```&#xA;&#xA;And so wherever I spin up quadtask: local, dev, or prod - the replication will&#xA;happen to and from a different path in my litestream bucket!&#xA;&#xA;# Update&#xA;&#xA;I updated the `docker-entrypoint.sh` of my quadtask container to look like this now:&#xA;&#xA;```bash&#xA;&#xA;# Restore the database if it does not already exist.&#xA;if [ -f /app/data/quadtask.db ]; then&#xA; echo &#34;Database already exists, skipping restore&#34;&#xA;else&#xA; echo &#34;No database found, restoring from replica&#34;&#xA; ENVIRONMENT=&#34;prod&#34; litestream restore -v /app/data/quadtask.db&#xA;fi&#xA;# Run litestream with your app as the subprocess.&#xA;exec litestream replicate -exec &#34;uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload --log-level debug&#34;&#xA;&#xA;```&#xA;&#xA;The `if` block checks if there&#39;s a db at the filepath it should be in in the continer - if it&#39;s not there is the little bit of magic to me right now...&#xA;&#xA;My litestream config has a parameterized `ENVIRONMENT` variable in the db path,&#xA;so by overwritting it for just the `restore` command, I can very simply always&#xA;pull a fresh copy of the prod database into an ephemeral container to test&#xA;things against real data in a very convenient way&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Migrate Github Issues to Kanboard</title>
    <id>https://pype.dev/migrate-github-issues-to-kanboard/</id>
    <updated>2025-08-07T14:43:27Z</updated>
    <published>2025-08-07T14:43:27Z</published>
    <link href="https://pype.dev/migrate-github-issues-to-kanboard/" rel="alternate" type="text/html"></link>
    <summary type="text">I am working on shifting everything, or as much as I reasonably can, related to dev for myself to on-prem, including git and CI/CD. So for Quadtask I had a...</summary>
    <content type="html">&lt;p&gt;I am working on shifting everything, or as much as I reasonably can, related to&#xA;dev for myself to on-prem, including git and CI/CD. So for Quadtask I had a&#xA;bunch of Github issues that I wanted to migrate to my kanboard instance, gpt-5&#xA;did a bang-up job on this script&lt;/p&gt;&#xA;&lt;p&gt;It gets each issue, creates a tag for each label, creates the kanboard ticket, then closes the github issue&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;#!/bin/bash&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# GitHub to Kanboard Issue Migration Script&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Uses GitHub CLI (gh) and curl to migrate issues&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Exit on error&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; -e&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Check required environment variables&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; var in KANBOARD_URL KANBOARD_TOKEN GH_TOKEN QUADTASK_KANBOARD_PROJECT_ID&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;do&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt; -z &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;!var&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Error: &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$var&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; is not set&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;exit&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;done&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# GitHub repository (default: pypeaday/quadtask)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;GITHUB_REPO&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;GITHUB_REPO&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;:-&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;pypeaday/quadtask&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Kanboard API endpoint&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;KANBOARD_API&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$KANBOARD_URL&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/jsonrpc.php&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Get all open issues from GitHub&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Fetching open issues from &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$GITHUB_REPO&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;...&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;ISSUES_JSON&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;gh issue list --repo &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$GITHUB_REPO&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; --state open --limit &lt;span class=&#34;m&#34;&gt;1000&lt;/span&gt; --json number,title,body,labels&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Count issues&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;ISSUE_COUNT&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$ISSUES_JSON&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq &lt;span class=&#34;s1&#34;&gt;&amp;#39;. | length&amp;#39;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Found &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$ISSUE_COUNT&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; open issues&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Process each issue&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$ISSUES_JSON&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq -c &lt;span class=&#34;s1&#34;&gt;&amp;#39;.[]&amp;#39;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;read&lt;/span&gt; -r issue&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;do&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# Extract issue details&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;NUMBER&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$issue&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq -r &lt;span class=&#34;s1&#34;&gt;&amp;#39;.number&amp;#39;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;TITLE&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$issue&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq -r &lt;span class=&#34;s1&#34;&gt;&amp;#39;.title&amp;#39;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;BODY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$issue&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq -r &lt;span class=&#34;s1&#34;&gt;&amp;#39;.body // &amp;#34;&amp;#34;&amp;#39;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# Extract label names as a JSON array&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;LABELS_JSON&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$issue&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq -c &lt;span class=&#34;s1&#34;&gt;&amp;#39;[.labels[]?.name] // []&amp;#39;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# Prepare Kanboard task data&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;REQUEST_DATA&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;jq -n &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        --arg method &lt;span class=&#34;s2&#34;&gt;&amp;#34;createTask&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        --argjson id &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        --arg jsonrpc &lt;span class=&#34;s2&#34;&gt;&amp;#34;2.0&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        --arg title &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$TITLE&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        --arg description &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$BODY&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        --arg project_id &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$QUADTASK_KANBOARD_PROJECT_ID&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s1&#34;&gt;&amp;#39;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;            &amp;#34;jsonrpc&amp;#34;: $jsonrpc,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;            &amp;#34;method&amp;#34;: $method,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;            &amp;#34;id&amp;#34;: $id,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;            &amp;#34;params&amp;#34;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;                &amp;#34;title&amp;#34;: $title,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;                &amp;#34;description&amp;#34;: $description,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;                &amp;#34;project_id&amp;#34;: $project_id&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;            }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;        }&amp;#39;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# Create task in Kanboard&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Creating task: &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$TITLE&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;RESPONSE&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;curl -s -X POST &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        -H &lt;span class=&#34;s2&#34;&gt;&amp;#34;Content-Type: application/json&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        -u &lt;span class=&#34;s2&#34;&gt;&amp;#34;jsonrpc:&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$KANBOARD_TOKEN&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        -d &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$REQUEST_DATA&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$KANBOARD_API&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# Check for errors&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$RESPONSE&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq -e &lt;span class=&#34;s1&#34;&gt;&amp;#39;.error&amp;#39;&lt;/span&gt; &amp;gt; /dev/null&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Error creating task: &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$RESPONSE&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq -r &lt;span class=&#34;s1&#34;&gt;&amp;#39;.error.message&amp;#39;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nv&#34;&gt;TASK_ID&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$RESPONSE&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq -r &lt;span class=&#34;s1&#34;&gt;&amp;#39;.result&amp;#39;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Created task ID: &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$TASK_ID&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;# If there are labels, set them as Kanboard tags on the task&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$LABELS_JSON&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq &lt;span class=&#34;s1&#34;&gt;&amp;#39;length&amp;#39;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; -gt &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Setting tags on task &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$TASK_ID&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;: &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$LABELS_JSON&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq -r &lt;span class=&#34;s1&#34;&gt;&amp;#39;join(&amp;#34;, &amp;#34;)&amp;#39;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nv&#34;&gt;TAGS_REQUEST&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;jq -n &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                --arg jsonrpc &lt;span class=&#34;s2&#34;&gt;&amp;#34;2.0&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                --arg method &lt;span class=&#34;s2&#34;&gt;&amp;#34;setTaskTags&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                --argjson id &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                --arg project_id &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$QUADTASK_KANBOARD_PROJECT_ID&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                --arg task_id &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$TASK_ID&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                --argjson tags &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$LABELS_JSON&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;s1&#34;&gt;&amp;#39;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;                    jsonrpc: $jsonrpc,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;                    method: $method,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;                    id: $id,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;                    params: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;                        project_id: $project_id,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;                        task_id: $task_id,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;                        tags: $tags&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;                    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;                }&amp;#39;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nv&#34;&gt;TAGS_RESPONSE&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;curl -s -X POST &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                -H &lt;span class=&#34;s2&#34;&gt;&amp;#34;Content-Type: application/json&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                -u &lt;span class=&#34;s2&#34;&gt;&amp;#34;jsonrpc:&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$KANBOARD_TOKEN&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                -d &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$TAGS_REQUEST&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$KANBOARD_API&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$TAGS_RESPONSE&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq -e &lt;span class=&#34;s1&#34;&gt;&amp;#39;.error&amp;#39;&lt;/span&gt; &amp;gt; /dev/null&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Warning: Failed to set tags: &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$TAGS_RESPONSE&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq -r &lt;span class=&#34;s1&#34;&gt;&amp;#39;.error.message&amp;#39;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Tags set successfully&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;# Close the corresponding GitHub issue to avoid duplicates&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nv&#34;&gt;TASK_URL&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;KANBOARD_URL&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/?controller=TaskViewController&amp;amp;action=show&amp;amp;task_id=&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;TASK_ID&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Closing GitHub issue #&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$NUMBER&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; with comment linking to Kanboard task...&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; gh issue close &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$NUMBER&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; --repo &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$GITHUB_REPO&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; --comment &lt;span class=&#34;s2&#34;&gt;&amp;#34;Migrated to Kanboard task &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$TASK_ID&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;: &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$TASK_URL&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &amp;gt;/dev/null&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Closed GitHub issue #&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$NUMBER&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Warning: Failed to close GitHub issue #&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$NUMBER&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;----------------------------------------&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;done&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Migration completed&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Using Litestream to Backup QuadTask’s SQLite DB</title>
    <id>https://pype.dev/using-litestream-to-backup-quadtasks-sqlite-db/</id>
    <updated>2025-08-05T19:34:19Z</updated>
    <published>2025-08-05T19:34:19Z</published>
    <link href="https://pype.dev/using-litestream-to-backup-quadtasks-sqlite-db/" rel="alternate" type="text/html"></link>
    <summary type="text">This post will be a walkthrough of installing litestream in a docker container that runs my FastAPI app in order to replicate the sqlite db in the data...</summary>
    <content type="text">&#xA;# Litestream&#xA;&#xA;This post will be a walkthrough of installing [[litestream]] in a docker container&#xA;that runs my FastAPI app in order to replicate the sqlite db in the data volume&#xA;currently hosted in Fly&#39;s volume manager to my MinIO instance. From there, on&#xA;my development machine I can use litestream to restore the prod database to my&#xA;dev environment to practice whatever I may need to practice with real&#xA;production data!&#xA;&#xA;## Dockerfile&#xA;&#xA;Installing litestream in the dockerfile is 2-3 lines of code - no sweat. Configuration file is further down the post.&#xA;&#xA;```dockerfile&#xA;FROM python:3.11-slim&#xA;WORKDIR /app&#xA;&#xA;# Install uv&#xA;COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/&#xA;&#xA;# Install litestream&#xA;ADD https://github.com/benbjohnson/litestream/releases/download/v0.3.8/litestream-v0.3.8-linux-amd64-static.tar.gz /tmp/litestream.tar.gz&#xA;RUN tar -C /usr/local/bin -xzf /tmp/litestream.tar.gz&#xA;COPY etc/litestream.yml /etc/litestream.yml&#xA;&#xA;# Install dependencies&#xA;COPY requirements.txt .&#xA;RUN uv pip install --no-cache -r requirements.txt&#xA;&#xA;# Copy the rest of the application&#xA;COPY . .&#xA;&#xA;# Install the app package in development mode&#xA;RUN uv pip install -e .&#xA;&#xA;# Run the application&#xA;CMD [&#34;docker-entrypoint.sh&#34;]&#xA;&#xA;```&#xA;&#xA;## Litestream Configuration&#xA;&#xA;Taking care to set `ENVIRONMENT` appropriately in each environment, the&#xA;litestream configuration gets that env var templated out to the path for the&#xA;litestream target. See [docs](https://litestream.io/reference/config/#variable-expansion)&#xA;&#xA;```yaml&#xA;#/etc/litestream.yml&#xA;dbs:&#xA;- path: /app/data/quadtask.db&#xA;  replicas:&#xA;  - name: quadtask&#xA;    type: s3&#xA;    bucket: litestream&#xA;    path: quadtask-${ENVIRONMENT}&#xA;    endpoint: s3.example.com&#xA;    skip-verify: false&#xA;    region: us-east-1&#xA;```&#xA;&#xA;## Authentication&#xA;&#xA;In your docker container you&#39;ll need to set `LITESTREAM_ACCESS_KEY_ID` and&#xA;`LITESTREAM_SECRET_ACCESS_KEY` which you setup in Minio - see&#xA;[[setup-remote-minio-s3-backend-target-for-litestream]]. I have these set as&#xA;secrets in my fly configuration, and locally in a .env file that gets sourced&#xA;with my compose stack&#xA;&#xA;## Example Log from Dev&#xA;&#xA;My fly dev machine has this log message showing the `ENVIRONMENT` var `dev` gets expanded into the config so the s3 path includes `quadtask-dev`&#xA;&#xA;`replicating to: name=&#34;quadtask&#34; type=&#34;s3&#34; bucket=&#34;litestream&#34; path=&#34;quadtask-dev&#34; region=&#34;us-east-1&#34; endpoint=&#34;s3.&lt;redacted&gt;.com&#34; sync-interval=1s`&#xA;&#xA;## Example Usage for Local Development&#xA;&#xA;- [[using-litestream-to-restore-my-database-for-easy-development]]&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Setup Remote MinIO S3 Backend Target for Litestream</title>
    <id>https://pype.dev/setup-remote-minio-s3-backend-target-for-litestream/</id>
    <updated>2025-08-05T08:39:16Z</updated>
    <published>2025-08-05T08:39:16Z</published>
    <link href="https://pype.dev/setup-remote-minio-s3-backend-target-for-litestream/" rel="alternate" type="text/html"></link>
    <summary type="text">I am starting to think through some patterns for replicating sqlite databases, exploring them, standardizing on schemas/models I use across projects, etc......</summary>
    <content type="text">&#xA;## Intro&#xA;&#xA;I am starting to think through some patterns for replicating sqlite databases,&#xA;exploring them, standardizing on schemas/models I use across projects, etc...&#xA;Thanks to [Waylon](https://waylonwalker.com) I know about [[litestream]] and&#xA;finally I started playing with it. Their&#xA;[quickstart](https://litestream.io/getting-started/) is good, but it assumes&#xA;you&#39;ll run MinIO on the same machine you run litestream on.&#xA;&#xA;I, however, have MinIO setup in my homelab with the api endpoint accessible via&#xA;DNS - `s3.mydomain.com`.&#xA;&#xA;Before starting - I realize I left the credential aspect out - Litestream&#xA;explains how to setup API keys in MinIO for their application&#xA;[here](https://litestream.io/getting-started/#setting-up-minio)&#xA;&#xA;Basically after generating the keys I set `LITESTREAM_ACCESS_KEY_ID` and `LITESTREAM_SECRET_ACCESS_KEY` as env vars&#xA;&#xA;So let&#39;s see what happens and then get to [the fix]&#xA;&#xA;&#xA;```&#xA;⬢ [devbox] ❯ litestream replicate quadtask-prod.db s3://s3.example.com/litestream/qt.db    &#xA;2025/08/05 08:50:09 INFO litestream version=v0.3.13&#xA;2025/08/05 08:50:09 INFO initialized db path=/home/nic/projects/personal/quadtask/litestream/source/quadtask-prod.db&#xA;2025/08/05 08:50:09 INFO replicating to name=s3 type=s3 sync-interval=1s bucket=s3.example.com path=litestream/qt.db region=&#34;&#34; endpoint=&#34;&#34;&#xA;2025/08/05 08:50:10 INFO sync: new generation db=/home/nic/projects/personal/quadtask/litestream/source/quadtask-prod.db generation=209692854ccd85d5 reason=&#34;no generation exists&#34;&#xA;2025/08/05 08:50:10 ERROR monitor error db=/home/nic/projects/personal/quadtask/litestream/source/quadtask-prod.db replica=s3 error=&#34;cannot lookup bucket region: InvalidAccessKeyId: The AWS Access Key Id you provided does not exist in our records.\n\tstatus code: 403, request id: ERHZD4RD61Y8ADMD, host id: dOjPn5j8Oa+mkwOqROXDvCdKNxzxG0B8JJOPtGXDZA7qKxwAWqaSXhGYzK2mkoJQV7hJhaoJcag=&#34;&#xA;&#xA;```&#xA;&#xA;So that `403` is pretty simple... my login is wrong... but wait...&#xA;&#xA;`2025/08/05 08:50:09 INFO replicating to name=s3 type=s3 sync-interval=1s bucket=s3.example.com path=litestream/qt.db region=&#34;&#34; endpoint=&#34;&#34;`&#xA;&#xA;Notice this line - `endpoint=&#34;&#34;`... so `s3://s3.example.com` was not the right replacement for `s3://mybkt.localhost:9000/target.db`. Also the inferred `bucket` is the entire `s3.example.com`... &#xA;&#xA;Oh! Well I didn&#39;t specify a bucket in the subdomain - I did it with a route on the URL... &#xA;&#xA;ok let&#39;s try `litestream replicate quadtask-prod.db s3://litestream.example.com/qt.db`&#xA;&#xA;We got the same kind of error...&#xA;&#xA;`2025/08/05 08:53:45 INFO replicating to name=s3 type=s3 sync-interval=1s bucket=litestream.example.com path=qt.db region=&#34;&#34; endpoint=&#34;&#34;`&#xA;&#xA;This time the inferred bucket was `litestream.example.com`... ok that&#39;s consistent with above as well - so the endpoint is still wrong/null and the bucket inference is wrong...&#xA;&#xA;Turns out for Litestream, and probably many other tools that use s3-compatible storage, that there&#39;s an inference problem if the configuration leans on the shorthand `s3://` - [see this GitHub issue](https://github.com/benbjohnson/litestream/issues/398) and [this one about localhost](https://github.com/benbjohnson/litestream/issues/219). There&#39;s a few options for using your own `s3.mydomain.example`.&#xA;&#xA;## The Fix&#xA;&#xA;If you&#39;re familiar with the `awscli` then maybe you&#39;ve heard of a config option `AWS_S3_ENDPOINT_URL` which allows you to use the boto sdk with s3-compatibile resources while still using the `s3://` shorthand. Litestream has a way to set this configuration right on config:&#xA;&#xA;```yaml&#xA;dbs:&#xA;  - path: /home/nic/projects/personal/quadtask/litestream/source/quadtask-prod.db&#xA;    replicas:&#xA;      - type: s3&#xA;        bucket: litestream&#xA;        endpoint: s3.example.com  # &lt;---- right here!&#xA;        skip-verify: true  # set to false if you have TLS and want more security&#xA;        # note you acn set these sensitive values as env vars per the Litestream Quickstart&#xA;        # access-key-id: &lt;ACCESS-KEY-ID&gt;&#xA;        # secret-access-key: &lt;SECRET-ACCESS-KEY&gt;&#xA;```&#xA;&#xA;???+ danger &#34;UPDATE&#34;&#xA;&#xA;    I added a `path` key to give the backups a folder basically on s3, so under &#34;bucket: listream&#34; I have &#34;path: &lt;my desired path&gt;&#34;&#xA;&#xA;So with that config in place we can actually JUST `litestream replicate` from anywhere...&#xA;&#xA;```bash&#xA;⬢ [devbox] ❯ litestream replicate                                                      &#xA;time=2025-08-05T08:56:11.353-05:00 level=INFO msg=litestream version=v0.3.13&#xA;time=2025-08-05T08:56:11.353-05:00 level=INFO msg=&#34;initialized db&#34; path=/home/nic/projects/personal/quadtask/litestream/source/quadtask-prod.db&#xA;time=2025-08-05T08:56:11.353-05:00 level=INFO msg=&#34;replicating to&#34; name=s3 type=s3 sync-interval=1s bucket=litestream path=&#34;&#34; region=&#34;&#34; endpoint=s3.example.com&#xA;time=2025-08-05T08:56:12.399-05:00 level=INFO msg=&#34;write snapshot&#34; db=/home/nic/projects/personal/quadtask/litestream/source/quadtask-prod.db replica=s3 position=209692854ccd85d5/00000000:4152&#xA;time=2025-08-05T08:56:12.489-05:00 level=INFO msg=&#34;snapshot written&#34; db=/home/nic/projects/personal/quadtask/litestream/source/quadtask-prod.db replica=s3 position=209692854ccd85d5/00000000:4152 elapsed=89.994626ms sz=909437&#xA;time=2025-08-05T08:56:12.492-05:00 level=INFO msg=&#34;write wal segment&#34; db=/home/nic/projects/personal/quadtask/litestream/source/quadtask-prod.db replica=s3 position=209692854ccd85d5/00000000:0&#xA;time=2025-08-05T08:56:12.510-05:00 level=INFO msg=&#34;wal segment written&#34; db=/home/nic/projects/personal/quadtask/litestream/source/quadtask-prod.db replica=s3 position=209692854ccd85d5/00000000:0 elapsed=17.572784ms sz=4152&#xA;```&#xA;&#xA;!!! success &#34;It works!&#34;&#xA;    &#xA;    Notice that the endpoint is properly s3.example.com, and the bucket is litestream (the name of my taret bucket in MinIO)&#xA;&#xA;&gt; You can use a local config with `-c config.yaml` or something if you want to avoid the global `/etc/litestream.yml`&#xA;&#xA;## What About Restore?&#xA;&#xA;Should work just fine... Let&#39;s move the database on my host and see if I can use litestream to restore it&#xA;&#xA;```&#xA;nic in quadtask/litestream   database-clean-up   ×21  ×2  ×9 via   v3.11.10(quadtask)   (dev) 󰒄 &#xA;⬢ [devbox] ❯ mv ./source/quadtask-prod.db ./source/quadtask-prod.db.backup                 &#xA;&#xA;nic in quadtask/litestream   database-clean-up   ×21  ×2  ×9 via   v3.11.10(quadtask)   (dev) 󰒄 &#xA;⬢ [devbox] ❯ litestream restore ./source/quadtask-prod.db              &#xA;time=2025-08-05T09:06:25.826-05:00 level=INFO msg=&#34;restoring snapshot&#34; db=/home/nic/projects/personal/quadtask/litestream/source/quadtask-prod.db replica=quadtask-prod generation=209692854ccd85d5 index=0 path=/home/nic/projects/personal/quadtask/litestream/source/quadtask-prod.db.tmp&#xA;time=2025-08-05T09:06:25.843-05:00 level=INFO msg=&#34;restoring wal files&#34; db=/home/nic/projects/personal/quadtask/litestream/source/quadtask-prod.db replica=quadtask-prod generation=209692854ccd85d5 index_min=0 index_max=0&#xA;time=2025-08-05T09:06:25.845-05:00 level=INFO msg=&#34;downloaded wal&#34; db=/home/nic/projects/personal/quadtask/litestream/source/quadtask-prod.db replica=quadtask-prod generation=209692854ccd85d5 index=0 elapsed=2.103514ms&#xA;time=2025-08-05T09:06:25.856-05:00 level=INFO msg=&#34;applied wal&#34; db=/home/nic/projects/personal/quadtask/litestream/source/quadtask-prod.db replica=quadtask-prod generation=209692854ccd85d5 index=0 elapsed=10.871034ms&#xA;time=2025-08-05T09:06:25.856-05:00 level=INFO msg=&#34;renaming database from temporary location&#34; db=/home/nic/projects/personal/quadtask/litestream/source/quadtask-prod.db replica=quadtask-prod&#xA;&#xA;```&#xA;&#xA;The command `litestream restore &lt;db path&gt;` was confusing at first because I was trying to replicate to a new place, but couldn&#39;t get the config to line up. The general understanding here is DR I believe - so the configuration is relatively static and when you `restore` you are restoring a specific database, not just standing up a copy from a backup... &#xA;&#xA;!!! note &#34;But would we setup a copy from a backup?&#34;&#xA;&#xA;    ie. restore to a different file?&#xA;&#xA;Yes, but it&#39;s confusing - at least it was to me... it looks to me like litestream uses the path of a db as the identifier in the config, and you reference the config not by an object&#39;s name (if it has one) but by the `path`...&#xA;&#xA;So the command is `litestream restore -o &lt;output path&gt; &lt;db path&gt;`. This makes sense in light of the fact that the configuration is relative to this host - so `&lt;db path&gt;` being the path of the source db whose backup you are restoring from to `&lt;output path&gt;` makes some amount of sense... if I wanted to replicate to another machine, then THAT machine would need `/etc/litestream.yaml` and if the filesystem hierarchy was different then an appropriate `path` for the &#34;source&#34; of the db to replicate back to.&#xA;&#xA;```&#xA;⬢ [devbox] ❯ litestream restore -o /tmp/db ./source/quadtask-prod.db          &#xA;time=2025-08-05T09:09:04.784-05:00 level=INFO msg=&#34;restoring snapshot&#34; db=/home/nic/projects/personal/quadtask/litestream/source/quadtask-prod.db replica=quadtask-prod generation=209692854ccd85d5 index=0 path=/tmp/db.tmp&#xA;time=2025-08-05T09:09:04.797-05:00 level=INFO msg=&#34;restoring wal files&#34; db=/home/nic/projects/personal/quadtask/litestream/source/quadtask-prod.db replica=quadtask-prod generation=209692854ccd85d5 index_min=0 index_max=0&#xA;time=2025-08-05T09:09:04.799-05:00 level=INFO msg=&#34;downloaded wal&#34; db=/home/nic/projects/personal/quadtask/litestream/source/quadtask-prod.db replica=quadtask-prod generation=209692854ccd85d5 index=0 elapsed=2.128594ms&#xA;time=2025-08-05T09:09:04.800-05:00 level=INFO msg=&#34;applied wal&#34; db=/home/nic/projects/personal/quadtask/litestream/source/quadtask-prod.db replica=quadtask-prod generation=209692854ccd85d5 index=0 elapsed=610.75µs&#xA;time=2025-08-05T09:09:04.800-05:00 level=INFO msg=&#34;renaming database from temporary location&#34; db=/home/nic/projects/personal/quadtask/litestream/source/quadtask-prod.db replica=quadtask-prod&#xA;&#xA;```&#xA;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Docker Volume Mounts Link to an Inode</title>
    <id>https://pype.dev/docker-volume-mounts-link-to-an-inode/</id>
    <updated>2025-08-02T13:01:58Z</updated>
    <published>2025-08-02T13:01:58Z</published>
    <link href="https://pype.dev/docker-volume-mounts-link-to-an-inode/" rel="alternate" type="text/html"></link>
    <summary type="text">docker bind mounts are specified as filepaths - this is very intuitive. I want /path/to/directory on my host to be shared with /another/path/foo in a...</summary>
    <content type="text">&#xA;docker bind mounts are specified as filepaths - this is very intuitive. I want&#xA;/path/to/directory on my host to be shared with /another/path/foo in a&#xA;container. But what if /path/to/directory on the host is moved?&#xA;&#xA;This is a situation I have found myself in at home and it turns out that I&#39;m&#xA;actually in almost zero trouble thankfully...&#xA;&#xA;TLDR - I have a bunch of compose stacks in&#xA;/home/projects/homelab-compose/&lt;host&gt;/&lt;application&gt; and I want to move them to&#xA;/home/projects/homelap-mono/compose/&lt;host&gt;/&lt;application&gt;&#xA;&#xA;I don&#39;t want to take down all my stacks to do this because I don&#39;t yet have a&#xA;convenient way to do it - but can I just `mv .../homelab-compose&#xA;.../homelab-mono/compose` and be done with it?&#xA;&#xA;The issue is that some of my stacks use local volume mounts - ie. there is a&#xA;data volume on the host in&#xA;/home/projects/homelab-compose/&lt;host&gt;&lt;application&gt;/docker-data for some of the&#xA;applications... can I just move everything and docker is nonethewiser?&#xA;&#xA;Turns out the answer is mostly `yes` with some caveats to keep in mind..&#xA;&#xA;Let&#39;s start with why it works and then show an example...&#xA;&#xA;## Why&#xA;&#xA;This works because of how docker interprets the bind mount location initially&#xA;and with how `mv` is different from `cp`. When you speicify a volume mount for&#xA;docker, the engine determines which [[inode]] contains the metadata for the&#xA;filesystem object referenced by the original volume path `/path/to/directory`.&#xA;I think about this like a string path is a pointer to a lower level identifier&#xA;closer to the filesystem - if that pointer changes it doesn&#39;t affect the&#xA;pre-existing inode or data. So docker uses the inode that `/path/to/directory`&#xA;points to when the container starts up.&#xA;&#xA;The slight convenience in my case is that `mv` maintains the existing inode and&#xA;so the new filepath is irrelevant to that existing container that was spun up&#xA;with a now-non-existent host filepath.&#xA;&#xA;So if you can imagine then - I spun up several containers in&#xA;`///homelab-compose/...` with many stacks - and I want to just move all the&#xA;config files to new repo... thankfully, I actually can *just `mv`* everything&#xA;and because the `inode` locations dont&#39; change, the stacks are fine!&#xA;&#xA;!!! warning &#34;caveat&#34;&#xA;&#xA;    Is the next issue apparent? What happens to those files whose volume mount configurations specify .../homelab-compose/...? Well, if the stacks are brought down and back up then docker will create that filepath on the host and a new inode reference will be had by all... so that&#39;s a problem easily mitigated by some string replacement!&#xA;&#xA;!!! note &#34;another note&#34;&#xA;&#xA;&#xA;    Perhaps just don&#39;t keep data next to your configuration either... In most of my stacks I have a determined docker volume that&#39;s backed up etc. on my hosts and that&#39;s what I&#39;m moving towards on my desktop, but as of right now I&#39;ve put myself in an odd situation via not participating in a proper thinking exercise when standing up all these stacks on my desktop&#xA;&#xA;## Example&#xA;&#xA;Finally let&#39;s just see it in action quickly...&#xA;&#xA;I have a directory `/tmp/foo/source` with a compose file in it.&#xA;&#xA;```&#xA;❯ tree source       &#xA;source&#xA;└── docker-compose.yml&#xA;```&#xA;&#xA;That file is simple:&#xA;&#xA;```yaml&#xA;services:&#xA;  app:&#xA;    image: nginx&#xA;    ports:&#xA;      - &#34;8070:80&#34;&#xA;    volumes:&#xA;      - /tmp/foo/source:/usr/share/nginx/html&#xA;```&#xA;&#xA;Now I can spin that container up, exec in, drop a file in `/usr/share/nginx/html` and we&#39;ll see it in `/tmp/foo/source` as expected...&#xA;&#xA;```bash&#xA;nic in /tmp/foo   (dev)&#xA;❯ docker exec source-app-1 touch /usr/share/nginx/html/file.txt&#xA;&#xA;nic in /tmp/foo   (dev)&#xA;❯ tree source                                                       &#xA;source&#xA;├── docker-compose.yml&#xA;└── file.txt&#xA;&#xA;1 directory, 2 files&#xA;&#xA;```&#xA;&#xA;Now let&#39;s `mv` the `source` directory somewhere else and see what happens&#xA;&#xA;```&#xA;nic in /tmp/foo   (dev)&#xA;❯ mv source target &#xA;&#xA;nic in /tmp/foo   (dev)&#xA;❯ tree target &#xA;target&#xA;└── source&#xA;    ├── docker-compose.yml&#xA;    └── file.txt&#xA;&#xA;2 directories, 2 files&#xA;&#xA;```&#xA;&#xA;OK everything is there - now let&#39;s drop another file in the container - remember the compose file still has the host path as `/tmp/foo/source`, not `/tmp/foo/target/source`.&#xA;&#xA;```&#xA;nic in /tmp/foo   (dev)&#xA;❯ docker exec source-app-1 touch /usr/share/nginx/html/another-file.txt&#xA;&#xA;nic in /tmp/foo   (dev)&#xA;❯ tree target                                                          &#xA;target&#xA;└── source&#xA;    ├── another-file.txt  # BAM! New file still here...&#xA;    ├── docker-compose.yml&#xA;    └── file.txt&#xA;&#xA;2 directories, 3 files&#xA;```&#xA;## Few Things&#xA;1. `cp` as noted before, creates new `inodes` and so if I were to have `cp -r`&#xA;   that `source` directory to `target` then the container would&#39;ve dropped&#xA;er exec source-app-1 touch /usr/share/nginx/html/another-file.txc in /tmp/foo   (dev) 󰒄 󱔎 NO PYTHON ENVIORNMENT SET t&#xA;`another-file.txt` to `/tmp/source` and we&#39;d be in a pretty confusing state&#xA;&#xA;2. Let me stress again the importance of managing your docker volumes in a sane&#xA;   way... I have on any of my hosts a `/path/to/docker/data` which is backed up&#xA;in a way that makes sense for the host (usually zfs + sanoid, otherwise restic&#xA;backup TO a remote zfs dataset - see&#xA;[[using-restic-to-backup-my-home-directory#Intro]])&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>You suck at git - but it’s honestly fine</title>
    <id>https://pype.dev/you-suck-at-git-but-its-honestly-fine/</id>
    <updated>2025-07-21T05:20:07Z</updated>
    <published>2025-07-21T05:20:07Z</published>
    <link href="https://pype.dev/you-suck-at-git-but-its-honestly-fine/" rel="alternate" type="text/html"></link>
    <summary type="text">I just started listening to localfirst.fm podcast podcast and would recommend it after 2 episodes. In the first episode, the hosts discuss where the term...</summary>
    <content type="html">&lt;h2 id=&#34;git-is-for-everyone&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Git is for everyone&lt;/span&gt; &lt;a href=&#34;#git-is-for-everyone&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I just started listening to &lt;a href=&#34;https://www.localfirst.fm/&#34;&gt;localfirst.fm podcast&lt;/a&gt;&#xA;podcast and would recommend it after 2 episodes. In the first episode, the&#xA;hosts discuss where the term &lt;code&gt;localfirst&lt;/code&gt; comes from, what it means, and&#xA;examples of some localfirst, or semi-localfirst projects. One of them is &lt;code&gt;git&lt;/code&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;the de-facto standard by which developers share code today.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;There&amp;rsquo;s a reason it&amp;rsquo;s the standard. I&amp;rsquo;m not arguing that it&amp;rsquo;s perfect, and&#xA;there&amp;rsquo;s new abstractions that may help people adopt usage like&#xA;&lt;a href=&#34;https://github.com/jj-vcs/jj&#34;&gt;jujutsu&lt;/a&gt;, but ultimately &lt;code&gt;git&lt;/code&gt; is a great tool,&#xA;and anyone can use it who works with text files (lookin at you book-writing&#xA;nerds)&lt;/p&gt;&#xA;&lt;p&gt;But as I was enjoying the pod the co-host/guest said &amp;ldquo;and we all know the git user&#xA;experience isn&amp;rsquo;t that great&amp;rdquo;&lt;/p&gt;&#xA;&lt;div class=&#34;admonition danger&#34;&gt;&#xA;&lt;p class=&#34;admonition-title&#34;&gt;heavy sigh&lt;/p&gt;&#xA;&lt;p&gt;Git isn&amp;rsquo;t that hard - you probably just aren&amp;rsquo;t that good at it&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;&lt;h2 id=&#34;it-s-ok&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;It’s OK&lt;/span&gt; &lt;a href=&#34;#it-s-ok&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Don&amp;rsquo;t hear me say that you suck at git like that&amp;rsquo;s a bad thing&amp;hellip; It&amp;rsquo;s &lt;em&gt;totally&#xA;fine&lt;/em&gt; to not be a wizard. Many people can use git like 80-90% efficiently for&#xA;their own use cases. In fact, my usage of git doesn&amp;rsquo;t fall into any perfectly&#xA;established patterns, and the decisions I make are not always the same (the&#xA;overplayed rebase vs merge-upstream argument&amp;hellip; I do both, it doesn&amp;rsquo;t matter,&#xA;squash your crap at the end anyways&amp;hellip;)&lt;/p&gt;&#xA;&lt;p&gt;So continue to collaborate - checkout your feature branches, pull in&#xA;&lt;code&gt;origin/main&lt;/code&gt; after a PR, ask for help with a rebase for the 69th time if you&#xA;need to&lt;/p&gt;&#xA;&lt;div class=&#34;admonition danger&#34;&gt;&#xA;&lt;p class=&#34;admonition-title&#34;&gt;Danger&lt;/p&gt;&#xA;&lt;p&gt;But quit your stupid annoying bitching&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;&lt;h2 id=&#34;seriously&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Seriously&lt;/span&gt; &lt;a href=&#34;#seriously&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Honestly, I learned &lt;em&gt;about&lt;/em&gt; git 8 years ago when I started my first job as a&#xA;data scientist. I was told by another developer, Jokko,&#xA;that it was the standard for collaboration&amp;hellip; only issue was that almost no one&#xA;in our division even used it. Or if they did it was at the end of a project,&#xA;after sharing code on share drives and OneDrive, at the very end we&amp;rsquo;d see &lt;code&gt;git init&lt;/code&gt;, &lt;code&gt;git add .&lt;/code&gt;, &lt;code&gt;git commit -m &amp;quot;pushed to git&amp;quot;&lt;/code&gt;, &lt;code&gt;git push&lt;/code&gt;&amp;hellip; literally 0&#xA;value, or at least no more value than&#xA;&lt;code&gt;my_project_final_FINAL_v2_project-over-now.zip&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;It took me a few weeks of on-the-job git usage, practicing way over complicated&#xA;git flows and talking about git with the few people around me who knew it, for&#xA;me to become a go-to resource&amp;hellip; I was and am honestly still annoyed about&#xA;it&amp;hellip; It didn&amp;rsquo;t take that long, or that much effort, to get pretty comfortable&#xA;with git. There&amp;rsquo;s tons of UIs (with their own flaws), TUIs, and resources for&#xA;learning the few things that will make you stand out as a git wizard:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;can you rebase onto a new root commit?&lt;/li&gt;&#xA;&lt;li&gt;can you pull in changes from someone else&amp;rsquo;s feature branch?&lt;/li&gt;&#xA;&lt;li&gt;if you find yourself in &lt;code&gt;detached HEAD state&lt;/code&gt; are you panicked?&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Just make a directory, &lt;code&gt;git init&lt;/code&gt;, and start shitting all over text files&amp;hellip;&#xA;make branches, reconcile differences, just freaking practice for 10 minutes&lt;/p&gt;&#xA;&lt;h2 id=&#34;end&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;End&lt;/span&gt; &lt;a href=&#34;#end&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I was triggered I guess listening to this podcast episode&amp;hellip; It&amp;rsquo;s fine to not&#xA;be an expert, it&amp;rsquo;s fine to just use the 3 or 4 commands you probably need (&lt;code&gt;git checkout -b, rebase origin/main, merge feature/branch, push&lt;/code&gt;), I am happy to&#xA;help people with git everyday - like I said above, I am somehow a go-to&#xA;resource for git in my workplace&amp;hellip;. (heck, even one of my managers asks me to&#xA;squash all the commits on his feature branches for him before it&amp;rsquo;s merged to&#xA;main&amp;hellip; it&amp;rsquo;s fine)&lt;/p&gt;&#xA;&lt;p&gt;But the user experience isn&amp;rsquo;t bad, so quit your bitching.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;details class=&#34;admonition note&#34;&gt;&#xA;&lt;summary class=&#34;admonition-title&#34;&gt;phone notes&lt;/summary&gt;&#xA;&lt;p&gt;hot take, if you complain about git then you don&amp;rsquo;t it&amp;hellip; and that&amp;rsquo;s fine but&#xA;shut up. I love git,I use it in a way that&amp;rsquo;s productive for me, and when I hear&#xA;people complain all they ever say is &amp;ldquo;git is hard&amp;rdquo; and &amp;ldquo;why is rebasing so&#xA;hard?!?!&amp;rdquo;&#xA;but they don&amp;rsquo;t get it, and that&amp;rsquo;s fine. you can use git inefficiently, as a&#xA;requirement of your job, and not enjoy it. but don&amp;rsquo;t bitch, because with 10&#xA;minutes of practice you could gain some real fluency in rebasing&lt;/p&gt;&#xA;&lt;/details&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Add yourself to www-data to view your Nextcloud data on the filesystem</title>
    <id>https://pype.dev/add-yourself-to-www-data-to-view-your-nextcloud-data-on-the-filesystem/</id>
    <updated>2025-07-17T07:38:09Z</updated>
    <published>2025-07-17T07:38:09Z</published>
    <link href="https://pype.dev/add-yourself-to-www-data-to-view-your-nextcloud-data-on-the-filesystem/" rel="alternate" type="text/html"></link>
    <summary type="text">I am working on using gotify-cli-for-notifying-me-of-nextcloud-uploads and I&#39;ll start by running the gotify cli as my user so I&#39;ll need to be able to see the...</summary>
    <content type="text">&#xA;I am working on using [[gotify-cli-for-notifying-me-of-nextcloud-uploads]] and&#xA;I&#39;ll start by running the gotify cli as my user so I&#39;ll need to be able to see&#xA;the directory in the filesystem that Nextcloud stores the data in.&#xA;&#xA;That folder on disk is owned by `www-data` (see [[nextcloud-permissions-with-zfs-and-ansible-nas]]&#xA;&#xA;Turns out it&#39;s my computer and I can do what I want so I just add myself to the&#xA;`www-data` group instead of running the `gotify cli` as `root`&#xA;&#xA;# Bonus&#xA;&#xA;You can remove users from groups with `gpasswd -d username groupname`&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>gotify cli for notifying me of nextcloud uploads</title>
    <id>https://pype.dev/gotify-cli-for-notifying-me-of-nextcloud-uploads/</id>
    <updated>2025-07-16T20:33:25Z</updated>
    <published>2025-07-16T20:33:25Z</published>
    <link href="https://pype.dev/gotify-cli-for-notifying-me-of-nextcloud-uploads/" rel="alternate" type="text/html"></link>
    <summary type="text">I was looking for a way to get notified from nextcloud when files were uploaded to a certain directory. This is because the upload is very spotty due to the...</summary>
    <content type="text">&#xA;# The Ask&#xA;&#xA;I was looking for a way to get notified from nextcloud when files were uploaded&#xA;to a certain directory. This is because the upload is very spotty due to the&#xA;physical environment of where the nextcloud client is, and once a file shows up&#xA;I have a job to do. So I was hoping nextcloud had an easy way to say &#34;if file&#xA;shows up in X folder, notify me&#34; but I can&#39;t find it...&#xA;&#xA;## Solution 2&#xA;&#xA;Since I already use gotify and they provide a [DOPE&#xA;CLI](https://github.com/gotify/cli) we can write a little bash script to work&#xA;at the filesystem level rather than the nextcloud level.&#xA;&#xA;## Permissions&#xA;&#xA;We&#39;ll need to make sure the user running this script has all the right read&#xA;permissions... In my exact case the file upload happens in a group folder,&#xA;which is easily found on the filesystem in the Nextcloud volume at&#xA;`.../data/__groupfolders/{id}/{rest of path}`. This was owned by `www-data` on&#xA;the host, see&#xA;[[add-yourself-to-www-data-to-view-your-nextcloud-data-on-the-filesystem]] if&#xA;you want but a simple `usermod -aG www-data &lt;me&gt;` does the trick.&#xA;&#xA;## The Script&#xA;&#xA;With a little AI magic to spruce up the messaging, the script basically looks like this:&#xA;&#xA;```bash&#xA;#!/bin/bash&#xA;&#xA;# Script to monitor sermon directory using gotify watch&#xA;# Used with a systemd service or standalone&#xA;# Can run in local or remote (SSH) mode&#xA;&#xA;# Configuration&#xA;&#xA;# Target directory to monitor&#xA;DIR_PATH=&#34;/path/to/watch&#34;&#xA;&#xA;# Mode: Set to &#34;ssh&#34; or &#34;local&#34;&#xA;# If ssh, will connect to SSH_HOST as SSH_USER to monitor the directory&#xA;# If local, will monitor the directory directly on this machine&#xA;MODE=&#34;ssh&#34;&#xA;&#xA;# Remote SSH settings (only used if MODE=&#34;ssh&#34;)&#xA;SSH_USER=&#34;youruser&#34;&#xA;SSH_HOST=&#34;yourserver&#34;&#xA;&#xA;# Log settings&#xA;LOG_DIR=&#34;$HOME/.local/state/sermon-monitor&#34;&#xA;LOG_FILE=&#34;$LOG_DIR/sermon-monitor.log&#34;&#xA;MAX_LOG_SIZE_KB=1024 # 1MB max log size&#xA;&#xA;# Create log directory if it doesn&#39;t exist&#xA;mkdir -p &#34;$LOG_DIR&#34; 2&gt;/dev/null&#xA;&#xA;# Create or truncate log file if it&#39;s too large&#xA;if [ -f &#34;$LOG_FILE&#34; ] &amp;&amp; [ $(stat -c%s &#34;$LOG_FILE&#34; 2&gt;/dev/null || echo 0) -gt $((MAX_LOG_SIZE_KB * 1024)) ]; then&#xA;  # Keep the last 20 lines when rotating&#xA;  tail -n 20 &#34;$LOG_FILE&#34; &gt;&#34;${LOG_FILE}.tmp&#34; 2&gt;/dev/null &amp;&amp; mv &#34;${LOG_FILE}.tmp&#34; &#34;$LOG_FILE&#34; 2&gt;/dev/null&#xA;  echo &#34;$(date &#39;+%Y-%m-%d %H:%M:%S&#39;) - Log file rotated due to size limit&#34; &gt;&gt;&#34;$LOG_FILE&#34;&#xA;fi&#xA;&#xA;# Ensure log file exists&#xA;touch &#34;$LOG_FILE&#34; 2&gt;/dev/null&#xA;&#xA;# Log function&#xA;log() {&#xA;  echo &#34;$(date &#39;+%Y-%m-%d %H:%M:%S&#39;) - $1&#34; | tee -a &#34;$LOG_FILE&#34;&#xA;}&#xA;&#xA;# Create a temp file to store the previous state&#xA;TEMP_DIR=&#34;/tmp/gotify-watcher&#34;&#xA;PREV_STATE_FILE=&#34;$TEMP_DIR/previous_state.txt&#34;&#xA;mkdir -p &#34;$TEMP_DIR&#34; 2&gt;/dev/null || true&#xA;&#xA;# Function to get directory listing based on mode&#xA;get_directory_listing() {&#xA;  if [ &#34;$MODE&#34; = &#34;ssh&#34; ]; then&#xA;    # Remote mode - use SSH&#xA;    ssh $SSH_USER@$SSH_HOST &#34;ls -la &#39;$DIR_PATH&#39; | grep -v &#39;^\.\.$&#39; | grep -v &#39;^\.$&#39;&#34; ||&#xA;      echo &#34;Error: Failed to connect to $SSH_HOST&#34;&#xA;  else&#xA;    # Local mode - direct access&#xA;    if [ -d &#34;$DIR_PATH&#34; ]; then&#xA;      ls -la &#34;$DIR_PATH&#34; | grep -v &#39;^\.\.$&#39; | grep -v &#39;^\.$&#39;&#xA;    else&#xA;      echo &#34;Error: Directory $DIR_PATH does not exist locally&#34;&#xA;    fi&#xA;  fi&#xA;}&#xA;&#xA;# Removed unused function - was leftover from previous version&#xA;&#xA;# Display startup message based on mode&#xA;if [ &#34;$MODE&#34; = &#34;ssh&#34; ]; then&#xA;  log &#34;Starting sermon file monitor for $SSH_USER@$SSH_HOST:$DIR_PATH (SSH mode)&#34;&#xA;else&#xA;  log &#34;Starting sermon file monitor for $DIR_PATH (local mode)&#34;&#xA;fi&#xA;&#xA;# Run initial check to establish baseline&#xA;CURRENT_LISTING=$(get_directory_listing)&#xA;echo &#34;$CURRENT_LISTING&#34; &gt;&#34;$PREV_STATE_FILE&#34;&#xA;log &#34;Initial state captured. Watching for changes.&#34;&#xA;&#xA;# Monitor continuously&#xA;while true; do&#xA;  # Sleep for 30 seconds between checks&#xA;  sleep 30&#xA;&#xA;  # Get current listing&#xA;  CURRENT_LISTING=$(get_directory_listing)&#xA;&#xA;  # Find new files by comparing with previous state&#xA;  NEW_FILES=$(diff --new-line-format=&#34;%L&#34; --old-line-format=&#34;&#34; --unchanged-line-format=&#34;&#34; \&#xA;    &#34;$PREV_STATE_FILE&#34; &lt;(echo &#34;$CURRENT_LISTING&#34;) | grep -v &#34;^total&#34; | grep -v &#34;^drwx&#34;)&#xA;&#xA;  # If new files found, notify&#xA;  if [ -n &#34;$NEW_FILES&#34; ]; then&#xA;    # Filter out directories and system entries, keep only regular files&#xA;    FILE_ENTRIES=$(echo &#34;$NEW_FILES&#34; | grep -v &#34;^d&#34; | grep -v &#34;^total&#34; | grep -v &#34;^\.$&#34; | grep -v &#34;^\.\.&#34;)&#xA;&#xA;    # Count how many actual files (non-empty lines)&#xA;    NEW_COUNT=$(echo &#34;$FILE_ENTRIES&#34; | grep -v &#34;^$&#34; | wc -l)&#xA;&#xA;    # Only proceed if we have actual files&#xA;    if [ &#34;$NEW_COUNT&#34; -gt 0 ]; then&#xA;      # Create notification message&#xA;      if [ &#34;$NEW_COUNT&#34; -eq 1 ]; then&#xA;        TITLE=&#34;New File Added&#34;&#xA;        # Extract filename from listing line&#xA;        FILENAME=$(echo &#34;$FILE_ENTRIES&#34; | awk &#39;{print $NF}&#39;)&#xA;        MESSAGE=&#34;New file detected: $FILENAME&#34;&#xA;      else&#xA;        TITLE=&#34;New Files Added&#34;&#xA;        # Format filenames only for readability&#xA;        FILELIST=$(echo &#34;$FILE_ENTRIES&#34; | awk &#39;{print $NF}&#39; | sort)&#xA;        MESSAGE=&#34;$NEW_COUNT new files detected:\n$FILELIST&#34;&#xA;      fi&#xA;&#xA;      # Send notification&#xA;      gotify push --title &#34;$TITLE&#34; &#34;$MESSAGE&#34;&#xA;      log &#34;Notification sent for new files: $NEW_COUNT&#34;&#xA;    fi&#xA;&#xA;    # Update previous state&#xA;    echo &#34;$CURRENT_LISTING&#34; &gt;&#34;$PREV_STATE_FILE&#34;&#xA;  fi&#xA;done&#xA;&#xA;# If we get here, gotify watch has exited&#xA;log &#34;gotify watch exited unexpectedly&#34;&#xA;exit 1&#xA;&#xA;```&#xA;&#xA;### Credentials&#xA;&#xA;As noted in the gotify repo - you can put the relevant credentials in a&#xA;`./cli.json` which is what I did since this is in a big repo of mine and that&#39;s&#xA;where the script executes from&#xA;&#xA;```json&#xA;{&#xA;  &#34;token&#34;: &#34;yourToken&#34;,&#xA;  &#34;url&#34;: &#34;https://gotify.example.com&#34;,&#xA;  &#34;defaultPriority&#34;: 6&#xA;}&#xA;```&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Using restic to backup my home directory</title>
    <id>https://pype.dev/using-restic-to-backup-my-home-directory/</id>
    <updated>2025-07-16T09:12:26Z</updated>
    <published>2025-07-16T09:12:26Z</published>
    <link href="https://pype.dev/using-restic-to-backup-my-home-directory/" rel="alternate" type="text/html"></link>
    <summary type="text">I need to backup my personal $HOME to my NAS cause there&#39;s a lot in there, and mostly my git projects with .env files all over. Plus some docker data</summary>
    <content type="text">&#xA;# Intro&#xA;&#xA;I need to backup my personal $HOME to my NAS cause there&#39;s a lot in there, and&#xA;mostly my git projects with .env files all over. Plus some docker data&#xA;&#xA;## Why Not ZFS?&#xA;&#xA;GREAT QUESTION! It&#39;s because I struggled getting all the syncoid/sanoid&#xA;requirements installed on my Aurora OS.... I like the immutable desktop trend,&#xA;but I don&#39;t understand rpm-ostree enough to properly get all the lower level&#xA;kernel stuff setup in a way I trust. So because I don&#39;t have ZFS at $HOME&#xA;what&#39;s a boy to do?&#xA;&#xA;`rsync` would probably work fine especially if I [[rsync-like-a-pro]] but I figured I could cobble together some other tech and broaden my horizons...&#xA;&#xA;## Enter restic&#xA;&#xA;Apparently [restic](https://restic.net/) has been around for a while, and you can run it in a container... awesome that&#39;s all I needed to hear...&#xA;&#xA;## How?&#xA;&#xA;I&#39;ll use a docker compose stack for this... typically I think running `restic`&#xA;right on the host is the way to go, but on my desktop I float between my host&#xA;and distroboxes and to keep things as simple as possible, even though less&#xA;efficient, I want to manage everything through containers as my homelab gets&#xA;built out and eventually I&#39;ll have a more full-featured ecosystem.&#xA;&#xA;## The Value&#xA;&#xA;You can find code below and an example repo that more or less is what I use for my desktop backup but that&#39;s primarily what I was after.... backing up the data on my desktop to my NAS in a way that:&#xA;&#xA;1. I wouldn&#39;t have to &#34;remember&#34; how I was doing it&#xA;&#xA;- I accomplish this by having good git repo organization and README files that explain my own usage patterns&#xA;&#xA;2. Tracked snapshots&#xA;&#xA;- I need some kind of snapshotting - `zfs` has spoiled me, and turns out `restic` has some amount of support for it&#xA;&#xA;3. Running in docker would be ideal for now so that I don&#39;t need to worry about installing specific binaries across machine while I build out my patterns&#xA;&#xA;With this setup I get to backup my $HOME to my NAS which contains 1. docker&#xA;volume info for all the AI workloads I run on my desktop and 2. all my&#xA;sensitive info in my git repos is at least backed up in a way that I can&#xA;recover `.env` files with relative ease...&#xA;&#xA;# Code&#xA;&#xA;Check out the [Example GH&#xA;Repo](https://github.com/pypeaday/docker-compose-restic) but I&#39;ll drop key file&#xA;contents here for a quick read if you&#39;re interested in some of the setup... but&#xA;the blog post mostly ends here&#xA;&#xA;## The Files&#xA;&#xA;We have a `docker-compose.yml` of course&#xA;&#xA;```yaml&#xA;services:&#xA;  backup:&#xA;    image: restic/restic:latest&#xA;    network_mode: host&#xA;    container_name: restic_backup&#xA;    hostname: restic-backup-runner&#xA;    env_file:&#xA;      - .env&#xA;    environment:&#xA;      # The location of the backup repository inside the container&#xA;      - RESTIC_REPOSITORY=/target&#xA;      # The location of the password file inside the container&#xA;      - RESTIC_PASSWORD_FILE=/password&#xA;    volumes:&#xA;      # --- Source and Config Mounts ---&#xA;      - &#34;${BACKUP_SOURCE}:/source:ro&#34;&#xA;      - &#34;${RESTIC_PASSWORD_FILE}:/password:ro&#34;&#xA;      - &#34;./backup-and-prune.sh:/usr/local/bin/backup-and-prune:ro&#34;&#xA;&#xA;      # --- Persistent Data Mounts ---&#xA;      - &#34;./.ssh:/root/.ssh:rw&#34;&#xA;      - &#34;./.cache:/root/.cache:rw&#34;&#xA;&#xA;    # Set the default entrypoint to our new script. This will be executed when&#xA;    # the container starts, unless overridden.&#xA;    entrypoint: [&#34;/usr/local/bin/backup-and-prune&#34;]&#xA;```&#xA;&#xA;Your `.env` file will need to look like this&#xA;&#xA;```bash&#xA;``# HOST related variables&#xA;# The source directory to back up (absolute path)&#xA;BACKUP_SOURCE=/home/nic&#xA;&#xA;# --- Restic Configuration ---&#xA;# The file containing the restic repository password (absolute path on host)&#xA;HOST_RESTIC_PASSWORD_FILE=/home/nic/projects/personal/homelab-mono/dataops/docker/.restic-password&#xA;# The SSH private key to use for connecting to the NAS (absolute path on host)&#xA;# It&#39;s recommended to use a dedicated key for this purpose.&#xA;SSH_PRIVATE_KEY_FILE=/home/nic/.skm/ghost/id_rsa&#xA;&#xA;# Container Env Vars&#xA;# the container makes the sftp connection using my credentials, but nonetheless the container needs them, so this isn&#39;t envrc stuff&#xA;&#xA;# --- SFTP/SSH Connection Details for the NAS ---&#xA;SFTP_USER=nic&#xA;SFTP_HOST=ghost&#xA;# The path on the NAS where the restic repository will be stored&#xA;SFTP_PATH=/tank/encrypted/nas/nic-home/&#xA;&#xA;# --- Restic Configuration ---&#xA;&#xA;RESTIC_REPOSITORY=/target&#xA;RESTIC_PASSWORD_FILE=/password&#xA;```&#xA;&#xA;And then the backup script that the container will execute is something like this:&#xA;&#xA;```bash&#xA;&#xA;#!/bin/sh&#xA;set -e # Exit immediately if a command exits with a non-zero status.&#xA;&#xA;# Construct the repository path from environment variables passed by docker-compose&#xA;REPO=&#34;sftp:${SFTP_USER}@${SFTP_HOST}:${SFTP_PATH}&#34;&#xA;&#xA;# 1. Run the backup&#xA;# -----------------&#xA;echo &#34;--- Starting backup for ${BACKUP_SOURCE} ---&#34;&#xA;restic backup /source --verbose -r &#34;${REPO}&#34;&#xA;echo &#34;--- Backup complete ---&#34;&#xA;&#xA;# 2. Clean up old snapshots according to the policy&#xA;# --------------------------------------------------&#xA;echo &#34;--- Pruning old snapshots ---&#xA;(Policy: keep last 7 daily, 4 weekly, 6 monthly)&#34;&#xA;restic forget \&#xA;    --prune \&#xA;    --keep-daily 7 \&#xA;    --keep-weekly 4 \&#xA;    --keep-monthly 6 \&#xA;    -r &#34;${REPO}&#34;&#xA;&#xA;echo &#34;--- Backup and prune process finished successfully ---&#34;&#xA;```&#xA;&#xA;## Systemd&#xA;&#xA;Finally there&#39;s a systemd unit and timer file in there so you can setup a systemd service for the backup&#xA;&#xA;### service&#xA;&#xA;```bash&#xA;&#xA;[Unit]&#xA;Description=Run Restic backup to NAS using Docker Compose&#xA;# We are running this as a user service, so we assume that the system-level&#xA;# docker.service is already running.&#xA;After=network-online.target&#xA;&#xA;[Service]&#xA;Type=oneshot&#xA;# Set the working directory to where your docker-compose.yml and .env file are located&#xA;WorkingDirectory=/home/user/nas-backup/docker&#xA;&#xA;# The command to execute. We use the full path to docker-compose for reliability.&#xA;# You may need to adjust this path if &#39;docker compose&#39; is installed elsewhere.&#xA;ExecStart=/usr/bin/docker compose run --rm backup&#xA;&#xA;[Install]&#xA;WantedBy=default.target&#xA;```&#xA;&#xA;### timer&#xA;&#xA;```bash&#xA;&#xA;[Unit]&#xA;Description=Run Restic backup job daily&#xA;&#xA;[Timer]&#xA;# Run daily at 2:00 AM&#xA;OnCalendar=daily&#xA;# Or uncomment for a specific time:&#xA;# OnCalendar=*-*-* 02:00:00&#xA;&#xA;# Run the backup immediately if the last scheduled run was missed (e.g., if the computer was off)&#xA;Persistent=true&#xA;&#xA;[Install]&#xA;WantedBy=timers.target&#xA;```&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Python editable installs and nested scripts</title>
    <id>https://pype.dev/python-editable-installs-and-nested-scripts/</id>
    <updated>2025-07-14T08:40:32Z</updated>
    <published>2025-07-14T08:40:32Z</published>
    <link href="https://pype.dev/python-editable-installs-and-nested-scripts/" rel="alternate" type="text/html"></link>
    <summary type="text">I have been working towards a standard structure for all my python projects - and I mean much more than just or something along those lines. But one of the...</summary>
    <content type="html">&lt;h1 id=&#34;intro&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Intro&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;I have been working towards a standard structure for all my python projects -&#xA;and I mean much more than just &lt;code&gt;uv init&lt;/code&gt; or something along those lines. But&#xA;one of the things that got me recently was starting to keep a &lt;code&gt;scripts/&lt;/code&gt; folder&#xA;that ran code based on what was in &lt;code&gt;src/&lt;/code&gt; or &lt;code&gt;app/&lt;/code&gt; (I&amp;rsquo;m working on that&amp;hellip;)&#xA;being installed in the virtual environment&amp;hellip; so I&amp;rsquo;d &lt;code&gt;uv pip install -e .&lt;/code&gt; or&#xA;&lt;code&gt;uv pip install -e src&lt;/code&gt; (kind of depends on the structure) and then in&#xA;&lt;code&gt;scripts/foo.py&lt;/code&gt; I&amp;rsquo;d have &lt;code&gt;from my_cool_code.module import thing&lt;/code&gt;&amp;hellip;.&lt;/p&gt;&#xA;&lt;p&gt;Running scripts has never been a problem&amp;hellip; but I&amp;rsquo;ve always kept them in the&#xA;root of the repo OR &lt;em&gt;inside&lt;/em&gt; &lt;code&gt;app&lt;/code&gt; or &lt;code&gt;src&lt;/code&gt; in a &lt;em&gt;nested&lt;/em&gt; directory&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;So here&amp;rsquo;s where I learned a little something about &lt;code&gt;python my_script.py&lt;/code&gt; vs&#xA;&lt;code&gt;python -m my_script&lt;/code&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;example&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Example&lt;/span&gt; &lt;a href=&#34;#example&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I setup a short example repo to illustrate the problem&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/pypeaday/python-e-example&#34;&gt;link to repo&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;The repo structure is very simple&amp;hellip;&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;python-e-example&#xA;  ├── foo.py&#xA;  ├── pyproject.toml&#xA;  ├── src&#xA;  │   ├── module.py&#xA;  ├── README.md&#xA;  └── scripts&#xA;      └── bar.py&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;code&gt;scripts/bar.py&lt;/code&gt; and &lt;code&gt;foo.py&lt;/code&gt; are the same code:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;src.module&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;my_func&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;my_func&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;and then &lt;code&gt;src/module.py&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;my_func&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;it worked!&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The rest of the structure is from &lt;code&gt;uv init&lt;/code&gt; basically, then &lt;code&gt;uv venv&lt;/code&gt; will make&#xA;your virtual environment, and &lt;code&gt;uv pip install -e .&lt;/code&gt; will install the library in&#xA;editable mode.&lt;/p&gt;&#xA;&lt;h3 id=&#34;so-what-s-the-problem&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;So what’s the problem?&lt;/span&gt; &lt;a href=&#34;#so-what-s-the-problem&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s run &lt;code&gt;foo.py&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nic in python-e-example   main   ×7 via   v3.13.1&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;python-e-example&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; 󰒄&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;⬢ &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;devbox&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; ❯ python foo.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;it worked!&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Nice! It works just like we&amp;rsquo;d expect&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;What about &lt;code&gt;python scripts/bar.py&lt;/code&gt;?&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nic in python-e-example   main   ×7 via   v3.13.1&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;python-e-example&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; 󰒄&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;⬢ &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;devbox&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; ❯ python scripts/bar.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Traceback &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;most recent call last&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  File &lt;span class=&#34;s2&#34;&gt;&amp;#34;/tmp/python-e-example/scripts/bar.py&amp;#34;&lt;/span&gt;, line 8, in &amp;lt;module&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    from src.module import my_func&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ModuleNotFoundError: No module named &lt;span class=&#34;s1&#34;&gt;&amp;#39;src&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;admonition danger&#34;&gt;&#xA;&lt;p class=&#34;admonition-title&#34;&gt;Come again for big fudge...&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;&lt;h3 id=&#34;ok-let-s-stay-calm-and-troubleshoot&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Ok let’s stay calm and troubleshoot&lt;/span&gt; &lt;a href=&#34;#ok-let-s-stay-calm-and-troubleshoot&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;What if we open a &lt;code&gt;python&lt;/code&gt; shell&amp;hellip;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Python 3.13.1 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;main, Dec &lt;span class=&#34;m&#34;&gt;19&lt;/span&gt; 2024, 14:32:25&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;Clang 18.1.8 &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; on linux&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Type &lt;span class=&#34;s2&#34;&gt;&amp;#34;help&amp;#34;&lt;/span&gt;, &lt;span class=&#34;s2&#34;&gt;&amp;#34;copyright&amp;#34;&lt;/span&gt;, &lt;span class=&#34;s2&#34;&gt;&amp;#34;credits&amp;#34;&lt;/span&gt; or &lt;span class=&#34;s2&#34;&gt;&amp;#34;license&amp;#34;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; more information.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;gt;&amp;gt;&amp;gt; from src.module import my_func&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;gt;&amp;gt;&amp;gt; my_func&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;!--markata-attribution--&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;it worked!&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;ok&amp;hellip; as expected it worked, and we&amp;rsquo;ve learned nothing&amp;hellip;&lt;/p&gt;&#xA;&lt;div class=&#34;admonition warning&#34;&gt;&#xA;&lt;p class=&#34;admonition-title&#34;&gt;implicit behavior&lt;/p&gt;&#xA;&lt;p&gt;We didn&amp;rsquo;t learn anything from the example but something is present that we&#xA;don&amp;rsquo;t see&amp;hellip; &lt;code&gt;python foo.py&lt;/code&gt; implicitly adds the path to the script to&#xA;&lt;code&gt;sys.path&lt;/code&gt; and so the &lt;code&gt;src&lt;/code&gt; library is in the same directory as the script&#xA;&lt;code&gt;foo.py&lt;/code&gt; so the library is on &lt;code&gt;sys.path&lt;/code&gt;&amp;hellip;. take note of this&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;&lt;h2 id=&#34;the-problem&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Problem&lt;/span&gt; &lt;a href=&#34;#the-problem&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Turns out &lt;code&gt;uv pip install .&lt;/code&gt; and &lt;code&gt;uv pip install -e .&lt;/code&gt; are &lt;em&gt;actually&lt;/em&gt; different&lt;/p&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250705005214_a83dd563.png&#34; alt=&#34;20250705005214_a83dd563.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;The editable install adds a &lt;code&gt;.pth&lt;/code&gt; file into &lt;code&gt;site-packages&lt;/code&gt; which acts as a&#xA;shell hook.&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# .venv/lib/python3.13/site-packages/__editable__.python_e_example-0.1.0.pth&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/tmp/python-e-example/src&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So when &lt;code&gt;python&lt;/code&gt; runs a script, the location of the script is&#xA;implicitly added to &lt;code&gt;sys.path&lt;/code&gt; as noted above.&#xA;The &lt;code&gt;python&lt;/code&gt; process invoked by &lt;code&gt;python foo.py&lt;/code&gt; has &lt;code&gt;$PWD&lt;/code&gt; on &lt;code&gt;sys.path&lt;/code&gt; which is &lt;code&gt;/tmp/python-e-example&lt;/code&gt; in&#xA;the example but &lt;code&gt;python scripts/bar.py&lt;/code&gt; has &lt;code&gt;/tmp/python-e-example/scripts&lt;/code&gt;&#xA;on &lt;code&gt;sys.path&lt;/code&gt;&amp;hellip; which means that &lt;code&gt;/tmp/python-e-example&lt;/code&gt; is NOT on &lt;code&gt;sys.path&lt;/code&gt;&#xA;in the process that&amp;rsquo;s running &lt;code&gt;scripts/bar.py&lt;/code&gt; and so the &lt;code&gt;src&lt;/code&gt; folder won&amp;rsquo;t be&#xA;searched by python because the &lt;code&gt;.pth&lt;/code&gt; file points to a directory that&amp;rsquo;s no on&#xA;the path!&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-solution&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Solution&lt;/span&gt; &lt;a href=&#34;#the-solution&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;We can instead of running the script &amp;ldquo;as a script&amp;rdquo; we can tell python to&#xA;execute it as as a module with &lt;code&gt;python -m scripts.bar&lt;/code&gt;. This is syntatically&#xA;similar to &lt;code&gt;python path/to/script.py&lt;/code&gt; but instead tells the python interpreter&#xA;to execute the script as a module so the path is replaced by import syntax.&lt;/p&gt;&#xA;&lt;div class=&#34;admonition note&#34;&gt;&#xA;&lt;p class=&#34;admonition-title&#34;&gt;This works for foo.py too&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;⬢ &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;devbox&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; ✗ python -m foo&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;it worked!&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;⬢ &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;devbox&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; ❯ python -m scripts.bar&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;it worked!&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;chatgpt&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;ChatGPT&lt;/span&gt; &lt;a href=&#34;#chatgpt&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;It&amp;rsquo;s noteworthy that jipity was helpful in exploring these issues I was running into&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://chatgpt.com/c/686d2a05-5b54-800f-8b84-1638c1b96840&#34;&gt;link to convo&lt;/a&gt;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Ghost</title>
    <id>https://pype.dev/ghost/</id>
    <updated>2025-07-11T20:23:35Z</updated>
    <published>2025-07-11T20:23:35Z</published>
    <link href="https://pype.dev/ghost/" rel="alternate" type="text/html"></link>
    <summary type="text">Ghost is my primary application server. These are the specs...</summary>
    <content type="text">&#xA;# Intro&#xA;&#xA;Ghost is my primary application server. These are the specs...&#xA;&#xA;&gt; I wrote about some of the specs in [[homelab-journey-part-1#current-homelab-setup]] but here is where I will keep up to date information&#xA;&#xA;## Why&#xA;&#xA;Why `ghost`? I don&#39;t know... I was going for a theme at one point it time, or&#xA;several points rather... and after giving up on the theatrics of a fully&#xA;consistent harry potter naming scheme across all my homelab entities, I decided&#xA;to just come up with some short aliases that were easy to type. So `ghost` was&#xA;born, and the backup server is `ghost-vault`.&#xA;&#xA;## CPU&#xA;&#xA;I have a `AMD Ryzen 7 5700G with Radeon Graphics @ 16x 4.426GHz` in this bad&#xA;boy... why this chip? Well I knew I wanted many cores, and I was previously on&#xA;a Ryzn 5 3600, which was fine but I noticed that as I started to develop with&#xA;containers more that I was going to want to take advnaatage of more cores...&#xA;&#xA;I also was pretty sure that the built-in graphics would be enough for the&#xA;acceleration requirements I had in mind - which was primarily [[jellyfin]].&#xA;&#xA;At this point in time, I think AMD was still beating Intel on most of the&#xA;benchmarks I tended to care about (I was watching channels like Bitwit and LTT&#xA;at the time of building this machine)&#xA;&#xA;So because of the moderate amount of cores and built-in GPU, I paid $229 for it&#xA;according to my Amazon history, and it&#39;s currently priced at $174, so that&#39;s a&#xA;pretty sweet deal if you&#39;re on AM4 and looking to upgrade in July of 2025&#xA;&#xA;## Memory&#xA;&#xA;I maxxed her out at 128 Gee Beez. I snagged that kit of Crucial that&#39;s all&#xA;black that we&#39;ve all seen on Amazon. I paid aboaut $90 for it, it&#39;s currently&#xA;priced way high for some reason, which is unfortunate. It&#39;s been totally fine&#xA;for me as far as memory performance goes - in that it&#39;s stable and I don&#39;t&#xA;think about it...&#xA;&#xA;## Boot&#xA;&#xA;I have a 1 TB NVMe in here to boot from. I think it&#39;s a Crucial P3&#xA;&#xA;## Storage&#xA;&#xA;Storage is the interesting bit, it&#39;s supposed to be the most rock solid but&#xA;it&#39;s also been the most fluid for me from a hardware perspective, and as of my&#xA;most recent case migration I think I&#39;m in a good spot..&#xA;&#xA;&gt; The case is a Sagitatius 8-bay NAS Chassis from aliexpress&#xA;&#xA;I use&#xA;[zfs](https://openzfs.github.io/openzfs-docs/Getting%20Started/index.html)&#xA;and recommend you do to.... but this isn&#39;t a post about that&#xA;&#xA;My primary zpool is a 12TB ZFS Mirror, and I have another 12TB ZFS Mirror as an&#xA;on-prem replica plugged into this same box.&#xA;&#xA;There is a 4TB drive that serves as frigate&#39;s media directory - I wanted a&#xA;dedicated drive due to the write-intensive nature of the NVR.&#xA;&#xA;&gt; I backup to an offsite box using syncoid&#xA;&#xA;## OS&#xA;&#xA;I am currently running Ubuntu Server 24.04&#xA;&#xA;I am eager for Ubuntu to get zfs in their release that contains the zfs data&#xA;corruption with encrypted datasets but I don&#39;t expect to see it until 26.04 at&#xA;the earliest _fingers crossed_.&#xA;&#xA;## KVM&#xA;&#xA;I recently purchased a [jetkvm](https://www.jetkvm.com/) and it&#39;s exactly what&#xA;I need for both my main server and my backup off-site... An amazingly simple&#xA;and elegant solution to remote KVM.&#xA;&#xA;## Applications&#xA;&#xA;Currently I use `docker compose` to manage practically everything. Stay tuned&#xA;for more about those things&#xA;&#xA;I also have a few ansible playbooks for setting up my shell and some utilities&#xA;on my computers, including the server. They&#39;re in&#xA;[github](https://github.com/pypeaday/ansible-playbooks)&#xA;&#xA;Find more at [[the-homelab]]&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>The Homelab</title>
    <id>https://pype.dev/the-homelab/</id>
    <updated>2025-07-11T20:22:51Z</updated>
    <published>2025-07-11T20:22:51Z</published>
    <link href="https://pype.dev/the-homelab/" rel="alternate" type="text/html"></link>
    <summary type="text">This is the landing page for my homelab posts. It isn&#39;t a feed because I will write things here and link out to relevant parts of the homelab.</summary>
    <content type="text">&#xA;# The Lab&#xA;&#xA;This is the landing page for my homelab posts. It isn&#39;t a feed because I will&#xA;write things here and link out to relevant parts of the homelab.&#xA;&#xA;I&#39;ll probably have notes about the hardware mostly here.&#xA;&#xA;## Primary Application Server&#xA;&#xA;My main server is called [[ghost]]&#xA;&#xA;## Current Homelab Setup&#xA;&#xA;&gt; I copied this our of [[homelab-journey-part-1#current-homelab-setup]] for now to stub out what this page will link to&#xA;&#xA;## Ad blocking | Pi-Hole&#xA;&#xA;Hardware: pi-3&#xA;&#xA;I have a Raspberry Pi 3 hardwired in that is running pi-hole so that&#39;s been a&#xA;part of my infrastructure now for a long time.&#xA;&#xA;## Router | OPNSense&#xA;&#xA;!!! note &#34;stats&#34;&#xA;&#xA;    CPU: i5-8700&#xA;&#xA;    Memory: 8GB of whatever was in the box&#xA;&#xA;    Storage: 1TB SSD&#xA;&#xA;My router is an old Optiplex SFF 5060 I got from Amazon for less than $100.&#xA;So I&#39;m running a x86 system for my router with&#xA;OpenSense on it. Just seemed it to be another home lab standard and I&#39;d like to&#xA;someday bring pi-hole over there or use AdGuard or integrate those two things&#xA;maybe a little bit more completely but right now they are mostly separate.&#xA;&#xA;## Networking | VLANs&#xA;&#xA;There&#39;s a&#xA;managed switch in there for some VLAN tomfoolery for my cameras and an IOT&#xA;network type of a thing.&#xA;&#xA;## Networking | VPN | Tailscale&#xA;&#xA;They&#39;re on tailscale as well so my DNS happens over tailscale.&#xA;&#xA;## My Desktop&#xA;&#xA;!!! note &#34;stats&#34;&#xA;&#xA;    CPU: Ryzen 7 5700X&#xA;&#xA;    GPU: Nvidia 3090&#xA;&#xA;    Memory: 64 GB&#xA;&#xA;    Storage: 4TB SSD + 2 TB HDD for zfs backup&#xA;&#xA;    OS: Universal Blue Aurora&#xA;&#xA;My daily-driver desktop is somewhat apart of my homelab now as I have a 3090 in&#xA;there with 20 GB of VRAM so I can run some heavier LLMs for self-hosted AI&#xA;workloads. Everything in that space runs in a container and then I manage&#xA;docker containers with compose stacks and portainer for visibility.&#xA;&#xA;### Applications&#xA;&#xA;Some of the apps I run here are ollama, open-webui, automatic1111&#39;s stable diffusion webui, whisper-webui&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Lua type hinting - undefined global</title>
    <id>https://pype.dev/lua-type-hinting-undefined-global/</id>
    <updated>2025-07-11T06:08:39Z</updated>
    <published>2025-07-11T06:08:39Z</published>
    <link href="https://pype.dev/lua-type-hinting-undefined-global/" rel="alternate" type="text/html"></link>
    <summary type="text">I have tons of linting errors in my nvim config, partly because I use Lazyvim plus a set of poorly written customizations that have traveled with me for a...</summary>
    <content type="html">&lt;p&gt;I have tons of linting errors in my nvim config, partly because I use Lazyvim&#xA;plus a set of poorly written customizations that have traveled with me for a&#xA;while. I try to re-work things and right now I&amp;rsquo;ve been revisiting my developer&#xA;setup. Well the LSP rrors as I&amp;rsquo;ve gone through my neovim config are ticking me&#xA;off - and this was the biggest one &amp;ldquo;Undefined global: vim&amp;rdquo;. I saw &lt;code&gt;vim.fn&lt;/code&gt;&#xA;everywhere but the LSP hated it&amp;hellip; turns out &lt;code&gt;vim&lt;/code&gt; is a given global and you&#xA;can help your lsp with this:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;---@diagnostic disable: undefined-global&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;-- vim is a global in Neovim Lua scripts&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For example:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;---@diagnostic disable: undefined-global&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;-- vim is a global in Neovim Lua scripts&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;s2&#34;&gt;&amp;#34;pypeaday&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;dir&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vim.fn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stdpath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;config&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;..&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/lua/pypeaday&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;config&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kd&#34;&gt;local&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;daily&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;require&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;pypeaday.daily&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;vim.api&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nvim_create_user_command&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;DailyNote&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;daily.check_and_open_daily_note&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{})&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;vim.api&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nvim_create_user_command&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Daily&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;daily.check_and_open_daily_note&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{})&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;vim.api&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nvim_create_user_command&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;BackLinks&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;daily.find_backlinks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{})&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;vim.keymap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;lt;leader&amp;gt;dn&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;daily.check_and_open_daily_note&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;desc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Open daily note&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;vim.keymap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;lt;leader&amp;gt;df&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;daily.find_daily_files&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;desc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Find daily files&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;vim.keymap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;lt;leader&amp;gt;dl&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;daily.find_backlinks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;desc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Find backlinks&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;end&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Testing a Postiz Change Locally (IT WORKS!)</title>
    <id>https://pype.dev/testing-a-postiz-change-locally/</id>
    <updated>2025-07-06T08:42:44Z</updated>
    <published>2025-07-06T08:42:44Z</published>
    <link href="https://pype.dev/testing-a-postiz-change-locally/" rel="alternate" type="text/html"></link>
    <summary type="text">I am working on a pipeline at home to integrate my blog with social media a little more. One of the things I want to do is automatically post my-thoughts to...</summary>
    <content type="text">&#xA;## Setup&#xA;&#xA;I am working on a pipeline at home to integrate my blog with social media a&#xA;little more. One of the things I want to do is automatically post&#xA;[[my-thoughts]] to [[nostr]]. [[postiz]] has nostr support that works just fine - login&#xA;with your [[nostr-hex-key]] and you&#39;re good to go to post notes to several of&#xA;the common relays. However for my testing I just wanted to post to a&#xA;[self-hosetd nostr relay](https://github.com/scsibug/nostr-rs-relay)&#xA;but there wasn&#39;t a way to override which relays were used. Well I submitted [this pr](https://github.com/gitroomhq/postiz-app/pull/824)&#xA;and hopefully it goes through. But before it did I was able to test the changes&#xA;by simply building the postiz image from my feature branch and deploying it at&#xA;home in leiu of the published image. It was super cool to see it work&#xA;&#xA;## Build and Deploy&#xA;&#xA;The build was easy after cloning the repo - I happened to already have `buildx` installed... it came with [aurora](https://docs.getaurora.dev/)&#xA;&#xA;`docker buildx build --platform linux/amd64 -f Dockerfile.dev -t registry.example.com/gitroomhq/postiz-app:nostr-test .`&#xA;&#xA;After building then I just update my compose file easy-peasy&#xA;&#xA;```yaml&#xA;services:&#xA;  postiz:&#xA;    # updated the image to my own from my registry&#xA;    image: resitry.example.com/gitroomhq/postiz-app:latest&#xA;    container_name: postiz&#xA;    restart: always&#xA;    env_file: .env&#xA;#####################&#xA;### REST OF COMPOSE FILE FROM THEIR REPO&#xA;```&#xA;&#xA;## Pics&#xA;&#xA;To test this my methodlogy was: 0. spin up nostr relay&#xA;&#xA;1. start postiz with my NOSTR_RELAY_OVERRIDES configuration for only my local relay&#xA;2. use an existing script to schedule a nostr post via the postiz REST API&#xA;3. use the UI to send the note to nostr&#xA;4. validate the note came through my relay&#xA;&#xA;So step 1 - does my script to schedule via the REST API work?&#xA;&#xA;```&#xA;postiz  | [0] 1|backend  | {&#xA;postiz  | [0] 1|backend  |   &#34;type&#34;: &#34;draft&#34;,&#xA;postiz  | [0] 1|backend  |   &#34;shortLink&#34;: false,&#xA;postiz  | [0] 1|backend  |   &#34;tags&#34;: [],&#xA;postiz  | [0] 1|backend  |   &#34;posts&#34;: [&#xA;postiz  | [0] 1|backend  |     {&#xA;postiz  | [0] 1|backend  |       &#34;integration&#34;: {&#xA;postiz  | [0] 1|backend  |         &#34;id&#34;: &#34;cmbgf5oko0001ra99r9vzv1fj&#34;&#xA;postiz  | [0] 1|backend  |       },&#xA;postiz  | [0] 1|backend  |       &#34;value&#34;: [&#xA;postiz  | [0] 1|backend  |         {&#xA;postiz  | [0] 1|backend  |           &#34;content&#34;: &#34;\nHere&#39;s a thought I had a while back:\n\n&gt; matduggan.com/what-would-a-kubernetes-2-0-look-like/\n\nThis article was longer than I had time to really consume but a heading caught my eye that I wanted to agree with - the author says k8s 2.0 may consider HCL instead of YAML. And as a recent terraform / open-tofu adopter I gotta say I would be ALL FOR THIS\n\nHere&#39;s the original link for more context: https://matduggan.com/what-would-a-kubernetes-2-0-look-like/\n        \n\n# devops # tech #k8s #nostr #plebchain&#34;,&#xA;postiz  | [0] 1|backend  |           &#34;image&#34;: []&#xA;postiz  | [0] 1|backend  |         }&#xA;postiz  | [0] 1|backend  |       ]&#xA;postiz  | [0] 1|backend  |     }&#xA;postiz  | [0] 1|backend  |   ],&#xA;postiz  | [0] 1|backend  |   &#34;date&#34;: &#34;2025-07-02T13:27:07.028Z&#34;&#xA;postiz  | [0] 1|backend  | }&#xA;```&#xA;&#xA;???+ success&#xA;&#xA;    After the first step my local build looks to have not broken this part of the app!&#xA;&#xA;Next was spinning up my own nostr relay - it&#39;s actually just `docker compose up`&#xA;&#xA;```yaml&#xA;services:&#xA;  nostr-relay:&#xA;    image: nostr-rs-relay:latest&#xA;    container_name: nostr-relay&#xA;    ports:&#xA;      - &#34;7000:8080&#34;&#xA;    environment:&#xA;      TZ: America/Chicago&#xA;    volumes:&#xA;      - ./data:/usr/src/app/db&#xA;      - ./config.toml:/usr/src/app/config.toml&#xA;    restart: unless-stopped&#xA;```&#xA;&#xA;Finally, can I send my note to my relay?&#xA;&#xA;I hit post in the UI and then checked coracle...&#xA;&#xA;Yes! Using [coracle.social](https://coracle.social) I can verify that my note went to my relay only&#xA;&#xA;![20250706122123_47b06d96.png](https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250706122123_47b06d96.png)&#xA;&#xA;## Fin&#xA;&#xA;So that was a fun way to get into postiz a little more and start to flesh out&#xA;what will be a testing-scenario for some pipelines I&#39;m building at home&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>💭 Build backend | uv</title>
    <id>https://pype.dev/thoughts-732/</id>
    <updated>2025-07-04T11:43:30Z</updated>
    <published>2025-07-04T11:43:30Z</published>
    <link href="https://pype.dev/thoughts-732/" rel="alternate" type="text/html"></link>
    <summary type="text">uv build backend ready for production! Dang... I need to visit my hatch builds, I love hatch&#39;s simplicity specifically w</summary>
    <content type="text">&#xA;&lt;a href=&#34;https://docs.astral.sh/uv/concepts/build-backend/&#34;&gt;&#xA;    &lt;img&#xA;        src=&#34;https://shots.wayl.one/shot/?url=https://docs.astral.sh/uv/concepts/build-backend/&amp;height=450&amp;width=800&amp;scaled_width=800&amp;scaled_height=450&amp;selectors=&#34;&#xA;        alt=&#34;shot of post - Build backend | uv&#34;&#xA;        height=450&#xA;        width=800&#xA;    &gt;&#xA;&lt;/a&gt;&#xA;&#xA;Here&#39;s my thought on &lt;a href=&#34;https://docs.astral.sh/uv/concepts/build-backend/&#34;&gt;Build backend | uv&lt;/a&gt;&#xA;&#xA;---&#xA;&#xA;uv build backend ready for production! Dang... I need to visit my hatch builds, I love hatch&#39;s simplicity specifically with versioning...  Not sure if it&#39;s worth actually switching to uv for my builds or not, but it is dang cool to see astral take on the python space with unbelievable improvements &#xA;&#xA;---&#xA;&#xA;!!! note&#xA;    This is one of [[ my-thoughts ]]. I picked this up from [Waylon Walker](https://waylonwalker.com)(https://thoughts.waylonwalker.com). It&#39;s a short note that I make about someone else&#39;s content online.  Learn more about the process [[ thoughts ]]&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>MCPHub with Windsurf</title>
    <id>https://pype.dev/mcphub-with-windsurf/</id>
    <updated>2025-07-03T08:42:31Z</updated>
    <published>2025-07-03T08:42:31Z</published>
    <link href="https://pype.dev/mcphub-with-windsurf/" rel="alternate" type="text/html"></link>
    <summary type="text">I came across mcphub today and got the motivation to try it out... I use AI tools like Windsurf and Roo across multiple devices and it&#39;d be awesome to have a...</summary>
    <content type="html">&lt;p&gt;I came across &lt;a href=&#34;https://github.com/samanhappy/mcphub&#34;&gt;mcphub&lt;/a&gt; today and got the motivation to try it out&amp;hellip; I use AI&#xA;tools like Windsurf and Roo across multiple devices and it&amp;rsquo;d be awesome to have&#xA;a simple mcp config - ie. a centralized hub to serve all my mcp servers and BAM&#xA;enter this github project. It was easy to spin up in docker, and then according&#xA;to Windsurf&amp;rsquo;s docs&#xA;&lt;a href=&#34;https://docs.windsurf.com/windsurf/cascade/mcp#mcp-config-json&#34;&gt;here&lt;/a&gt; the&#xA;setup is just naming a server and passing a serverUrl&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;mcpServers&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;hub&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;serverUrl&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;http://localhost:3000/sse&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250703134426_2c9dfa01.png&#34; alt=&#34;20250703134426_2c9dfa01.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;details class=&#34;admonition warning&#34; open&gt;&#xA;&lt;summary class=&#34;admonition-title&#34;&gt;Warning&lt;/summary&gt;&#xA;&lt;p&gt;The sse endpoint stuff is getting deprecated eventually - I didn&amp;rsquo;t want to&#xA;spend any time right now trying to get the newer things to work&amp;hellip; future&#xA;me/you will solve that problem&lt;/p&gt;&#xA;&lt;/details&gt;&#xA;&lt;h2 id=&#34;setup&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Setup&lt;/span&gt; &lt;a href=&#34;#setup&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I ran this in compose with this file&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;�services&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;mcphub&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;samanhappy/mcphub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;ports&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;3000:3000&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;volumes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;./mcp_settings.json:/app/mcp_settings.json&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;./data:/app/data&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;qdrant&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;qdrant/qdrant&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;container_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;qdrant&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;restart&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;unless-stopped&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;ports&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;6333:6333&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;deploy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;resources&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;limits&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;memory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;500m&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And at present the &lt;code&gt;mcp_settings.json&lt;/code&gt; file looks like this mostly:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;mcpServers&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;docker-mcp&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;command&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;uvx&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;args&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;docker-mcp&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;ragdocs&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;command&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;node&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;args&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;./node_modules/@qpd-v/mcp-server-ragdocs/build/index.js&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;env&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;#34;QDRANT_URL&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;http://localhost:6333&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;#34;EMBEDDING_PROVIDER&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;ollama&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;#34;OLLAMA_URL&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;http://localhost:11434&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;alwaysAllow&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;search_documentation&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;list_sources&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;test_ollama&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;add_documentation&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;disabled&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;sequential-thinking&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;command&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;npx&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;args&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;-y&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;@modelcontextprotocol/server-sequential-thinking&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;users&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;username&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;admin&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;password&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;redacted&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;isAdmin&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;details class=&#34;admonition note&#34; open&gt;&#xA;&lt;summary class=&#34;admonition-title&#34;&gt;Note&lt;/summary&gt;&#xA;&lt;p&gt;I assume here you have ollama running for ragdocs (in my screenshot you see I actually don&amp;rsquo;t right now anyways)&lt;/p&gt;&#xA;&lt;/details&gt;&#xA;&lt;p&gt;&lt;code&gt;docker compose up&lt;/code&gt; and we&amp;rsquo;re cooking at &lt;a href=&#34;http://localhost:3000&#34;&gt;http://localhost:3000&lt;/a&gt;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Nostr</title>
    <id>https://pype.dev/nostr/</id>
    <updated>2025-07-02T21:22:03Z</updated>
    <published>2025-07-02T21:22:03Z</published>
    <link href="https://pype.dev/nostr/" rel="alternate" type="text/html"></link>
    <summary type="text">???+ note &#34;How to start...&#34;</summary>
    <content type="text">&#xA;???+ note &#34;How to start...&#34;&#xA;&#xA;    This isn&#39;t a getting started with nostr - see [[getting-started-with-nostr]] for that&#xA;&#xA;[The nostr docs](https://nostr.com/)&#xA;&#xA;Nostr is a very intriguing protocol for communication that lends itself to a&#xA;decentrlized social media experience through the use of relays. I would love to&#xA;understand it more fully someday, but I am inclined to be in line with&#xA;almost anything decentrlized, and although the primary content in the&#xA;nostr-verse right now is bitcoin, I am sure that as time goes on, the need for&#xA;a truly free way to communicate will be necessary - and nostr won&#39;t solve every&#xA;problem, but I think it&#39;ll be a tool in the set of solutions we come up with.&#xA;It&#39;s secure, decentralized, actively worked on, and very flexible.&#xA;&#xA;???+ note &#34;NOSTR&#34;&#xA;&#xA;    Notes and Other Stuff Transmited over Relays&#xA;&#xA;## Decentralization&#xA;&#xA;Why does decentralization matter? Put simply - censorship. A founding principal&#xA;of America is free speech and in recent years our right to speak freely has&#xA;been put under severe fire.&#xA;&#xA;I&#39;ve crossed paths with people who very regularly talked about freedom of&#xA;speech but it wasn&#39;t until the last several years, mostly with covid that I&#xA;started to pay a little closer attention. I&#39;m not turning this post into any&#xA;long rant about anything specific, but I do know that many voices were silenced&#xA;on Facebook, Twitter/X, Insta, etc. Big Tech really threw the hammer down on&#xA;people - a simple example was the Ivermectin stuff... which in the last 2 years&#xA;has turned out to be a pretty effective treatment for many thousands of people!&#xA;&#xA;But why does that matter? It&#39;s because the platforms that existed which made it&#xA;possible for anyone to &#34;have an audience&#34; made harsh judgements about what&#xA;could and couldn&#39;t be on their platforms... There&#39;s pros and cons to this, but a&#xA;primary con I see is that the power to limit the spread of information was&#xA;pretty solely concentrated in the departments of these Big Tech firms that&#xA;allowed or disallowed certain things to be said and expressed on their&#xA;platforms.&#xA;&#xA;Nostr is different here in that there&#39;s no central command, no single data&#xA;center or hub.... Nostr is a protocol, like HTTP is a protocol... anyone can&#xA;send &#34;Notes and Other Stuff over Relays&#34; so developers can build any kind of UI&#xA;for it, and you as the user can subscribe to relays that tend to have&#xA;information you care about... in a sense it&#39;s kind of like subreddits but not&#xA;quite as organized (yet).... but unlike reddit, there&#39;s no central authority.&#xA;The closest it gets is that a relay may go down or someone may choose to close&#xA;one - no big, you just subscribe to other relays, or don&#39;t subscribe to relays&#xA;you don&#39;t want to see&#xA;&#xA;Another friend of mine likened this to RSS - and it&#39;s also not UNlike that, but&#xA;there&#39;s more to it - the notes are on the relays, there&#39;s encryption throughout&#xA;the protocol, and several other standards called NIPS that make nostr unique,&#xA;and I think bulletproof as we go into a future clouded by big government and&#xA;big tech collaboration.&#xA;&#xA;## Brief Usage&#xA;&#xA;As for a usage pattern with nostr I think you have to combine the ideas of&#xA;reddit, rss, and twitter...&#xA;&#xA;Some apps like coracle.social have nice support for building &#34;feeds&#34; and&#xA;&#34;lists&#34;... lists are combinations of tags (hashtags) and feeds are combinations&#xA;of lists - at least in the coracle world. This means you can use lists of tags&#xA;to discover content and users, create feeds of things you want to see regularly&#xA;(like your RSS feed subscriptions), follow other users (using their pub keys&#xA;see [## Follow Me]), and curate your social media experience in whatever way&#xA;you want.&#xA;&#xA;There&#39;s nostr apps specific to mobile (primal, snort) and desktop&#xA;(coracle.social). They help you set yourself up in different ways and to learn&#xA;more about how I got started then checkout [[getting-started-with-nostr]].&#xA;There&#39;s also content-driven nostr apps, for example [fountain]() is great for&#xA;music and podcasts that are distributed on the nostrverse, which feels like a&#xA;totally different world than when I use coracle to browse my tech or bible&#xA;related feeds.&#xA;&#xA;## End&#xA;&#xA;Nostr is a pretty cool thing taking shape... here&#39;s some related info&#xA;&#xA;[Thank God for nostr podcast](https://tgfb.com/podcasts/thank-god-for-nostr/)&#xA;&#xA;[nostr website](https://nostr.com/)&#xA;&#xA;&gt; Note these posts aren&#39;t available yet but they will show up on my RSS feed when they&#39;re published&#xA;&#xA;My post on [[getting-started-with-nostr]]&#xA;&#xA;My project on [[thoughts-to-nostr]]&#xA;&#xA;...&#xA;&#xA;## Follow Me&#xA;&#xA;![20250705122314_e9fbd0f7.png](https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250705122314_e9fbd0f7.png)&#xA;&#xA;???+ note &#34;my public key&#34;&#xA;&#xA;    npub1q3fsec2vcv99v80ga72dlv90qwkqmuxqcr6mdyumcmpkgudlhrespyurfj&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Nostr hex key</title>
    <id>https://pype.dev/nostr-hex-key/</id>
    <updated>2025-07-02T08:43:32Z</updated>
    <published>2025-07-02T08:43:32Z</published>
    <link href="https://pype.dev/nostr-hex-key/" rel="alternate" type="text/html"></link>
    <summary type="text">you can hexify your nostr key when you need to sometimes which I needed to for postiz (link with a thought I&#39;m sure I have on postiz)</summary>
    <content type="text">&#xA;you can hexify your [[nostr]] key when you need to sometimes which I needed to for [[postiz]] (link with a thought I&#39;m sure I have on postiz)&#xA;&#xA;```python&#xA;&#xA;# /// script&#xA;# requires-python = &#34;&gt;=3.8&#34;&#xA;# dependencies = [&#xA;#     &#34;bech32&#34;,&#xA;# ]&#xA;# ///&#xA;#&#xA;import os&#xA;&#xA;import bech32&#xA;&#xA;# Set your nsec... key to NOSTR_PRIVATE_KEY or bake it in...&#xA;nsec_key = os.environ.get(&#34;NOSTR_PRIVATE_KEY&#34;)&#xA;&#xA;&#xA;def decode_nsec(nsec_key):&#xA;    hrp, data = bech32.bech32_decode(nsec_key)&#xA;    if hrp != &#34;nsec&#34;:&#xA;        raise ValueError(&#34;Not a valid nsec key&#34;)&#xA;    decoded = bech32.convertbits(data, 5, 8, False)&#xA;    return bytes(decoded).hex()&#xA;&#xA;&#xA;# Example usage&#xA;raw_hex = decode_nsec(nsec_key)&#xA;print(f&#34;Raw hex private key: {raw_hex}&#34;)&#xA;```&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Github Star Sorter</title>
    <id>https://pype.dev/github-star-sorter/</id>
    <updated>2025-07-01T08:01:31Z</updated>
    <published>2025-07-01T08:01:31Z</published>
    <link href="https://pype.dev/github-star-sorter/" rel="alternate" type="text/html"></link>
    <summary type="text">I wrote a simple app to sort, tag, and create tickets at home for my github stars... As of right now I have 1.3k stars and no convenient way to view them or...</summary>
    <content type="html">&lt;p&gt;I wrote a simple app to sort, tag, and create tickets at home for my github&#xA;stars&amp;hellip; As of right now I have 1.3k stars and no convenient way to view them&#xA;or remember which ones were ones I actually wanted to do something with. This&#xA;simple UI makes scrolling the stars list easy, updates is easy, and the kicker&#xA;for me is Kanboard integration so I can click a button from the stars UI and&#xA;get a ticket made in my kanboard instance so that the work I want to do is in&#xA;front of me and not hidden by Github&amp;rsquo;s shockingly HORRIBLE UI.&lt;/p&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250701125804_c41ec692.png&#34; alt=&#34;20250701125804_c41ec692.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/pypeaday/gh-star-sorter&#34;&gt;GH Link&lt;/a&gt;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>💭 Switching pip to uv in a Dockerized Flask / Django App — Nick …</title>
    <id>https://pype.dev/thoughts-722/</id>
    <updated>2025-06-27T11:18:16Z</updated>
    <published>2025-06-27T11:18:16Z</published>
    <link href="https://pype.dev/thoughts-722/" rel="alternate" type="text/html"></link>
    <summary type="text">It&#39;s nice to see uv gaining popularity in so many places - and replacing vanilla pip with uv in containerized environmen</summary>
    <content type="text">&#xA;&lt;a href=&#34;https://nickjanetakis.com/blog/switching-pip-to-uv-in-a-dockerized-flask-or-django-app&#34;&gt;&#xA;    &lt;img&#xA;        src=&#34;https://shots.wayl.one/shot/?url=https://nickjanetakis.com/blog/switching-pip-to-uv-in-a-dockerized-flask-or-django-app&amp;height=450&amp;width=800&amp;scaled_width=800&amp;scaled_height=450&amp;selectors=&#34;&#xA;        alt=&#34;shot of post - Switching pip to uv in a Dockerized Flask / Django App — Nick Janetakis&#34;&#xA;        height=450&#xA;        width=800&#xA;    &gt;&#xA;&lt;/a&gt;&#xA;&#xA;Here&#39;s my thought on &lt;a href=&#34;https://nickjanetakis.com/blog/switching-pip-to-uv-in-a-dockerized-flask-or-django-app&#34;&gt;Switching pip to uv in a Dockerized Flask / Django App — Nick Janetakis&lt;/a&gt;&#xA;&#xA;---&#xA;&#xA;It&#39;s nice to see uv gaining popularity in so many places - and replacing vanilla pip with uv in containerized environments seems great due if for no other reason than the time you&#39;ll save in CI... A few years ago I refactored a disjointed container build process to use uv instead of pip, and due to the design of the build pipelines we went from 10-15 minute builds to 2-3 minutes... &#xA;&#xA;---&#xA;&#xA;!!! note&#xA;    This is one of [[ my-thoughts ]]. I picked this up from [Waylon Walker](https://waylonwalker.com)(https://thoughts.waylonwalker.com). It&#39;s a short note that I make about someone else&#39;s content online.  Learn more about the process [[ thoughts ]]&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>temporal</title>
    <id>https://pype.dev/temporal/</id>
    <updated>2025-06-24T21:21:43Z</updated>
    <published>2025-06-24T21:21:43Z</published>
    <link href="https://pype.dev/temporal/" rel="alternate" type="text/html"></link>
    <summary type="text">Temporal is a workflow orchestrator that I&#39;m interested in</summary>
    <content type="html">&lt;p&gt;&lt;a href=&#34;https://temporal.io/&#34;&gt;Temporal&lt;/a&gt; is a workflow orchestrator that I&amp;rsquo;m interested in&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Traefik and gRPC for Temporal at home</title>
    <id>https://pype.dev/traefik-and-grpc-for-temporal-at-home/</id>
    <updated>2025-06-24T20:55:42Z</updated>
    <published>2025-06-24T20:55:42Z</published>
    <link href="https://pype.dev/traefik-and-grpc-for-temporal-at-home/" rel="alternate" type="text/html"></link>
    <summary type="text">Someday I will potentially write up some stuff about temporal but for now it&#39;s a workflow orchestrator that I&#39;m interested in and I wanted to PoC it in my...</summary>
    <content type="text">&#xA;# Temporal Networking Woes&#xA;&#xA;Someday I will potentially write up some stuff about [[temporal]] but for now&#xA;it&#39;s a workflow orchestrator that I&#39;m interested in and I wanted to PoC it in&#xA;my homelab by replacing a simple cron job to build my blog with a temporal&#xA;workflow and activity. I was IMMEDIATELY thwarted by a networking error that&#xA;feels crazy to me but maybe won&#39;t be to others... so enjoy the problem and if&#xA;you&#39;re here from a Google search, I hope it&#39;s helpful.&#xA;&#xA;Getting started with Temporal I wanted to have the server and associated&#xA;components on my server, but I expected to be running workflows and workers&#xA;on another computer. &#xA;&#xA;For most of my apps I slap some [[traefik]] labels on&#xA;and we&#39;re good to go. But I got a wild set of errors trying to run a worker on&#xA;my desktop and connect it to the temporal server on my server over https.... it&#xA;ended up being because I needed to setup a special protocol in traefik for the&#xA;reverse proxy to appropriately proxy the grpc call.&#xA;&#xA;So I had a normal set of labels on my temporal container, went to run a worker&#xA;and got this nasty work of art&#xA;&#xA;```&#xA;RuntimeError: Failed client connect: `get_system_info` call error after connection: Status { code: Internal, message: &#34;protocol error: received message with invalid compression flag: 73 (valid flags are 0 and 1) while receiving response with status: 500 Internal Server Error&#34;, metadata: MetadataMap { headers: {&#34;content-type&#34;: &#34;text/plain; charset=utf-8&#34;, &#34;content-length&#34;: &#34;21&#34;, &#34;date&#34;: &#34;Wed, 25 Jun 2025 02:12:44 GMT&#34;} }, source: None }&#xA;```&#xA;&#xA;Thank God I had kind of seen this at work one other time in my life, and we&#xA;never fixed the issue there but I knew what it was... we had traefik acting as&#xA;a load balancer (as do I at home) and the traefik load balancer was &#34;balancing&#xA;traffic using https&#34;... no, I do not really know what I&#39;m saying. But what I do&#xA;know is that in order for the Temporal Server and Worker to communicate,&#xA;traefik has to properly route the traffic for gRPC instead of https.&#xA;&#xA;!!! warning &#34;&#34;&#xA;    I can&#39;t stress enough how little I know about the difference between https and grpc or why the load balancer cares... there&#39;s clearly something in the networking stack that is extremely relevant here&#xA;&#xA;But the fix is NOT hard thankfully, and it&#39;s even on [traefik&#39;s website](https://doc.traefik.io/traefik/user-guides/grpc/#traefik-configuration) - the warning annotation there tells you what you need - which is one more traefik label...&#xA;&#xA;```yaml&#xA;traefik.http.services.&lt;my-service-name&gt;.loadbalancer.server.scheme=h2c&#xA;```&#xA;&#xA;So after setting the loadbalancer.server.scheme to `h2c` I could run my worker just fine!&#xA;&#xA;![20250625021838_4d7104c2.png](https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250625021838_4d7104c2.png)&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Nextcloud PHP Opache Memory Consumption</title>
    <id>https://pype.dev/nextcloud-php-opache-memory-consumption/</id>
    <updated>2025-06-23T08:46:20Z</updated>
    <published>2025-06-23T08:46:20Z</published>
    <link href="https://pype.dev/nextcloud-php-opache-memory-consumption/" rel="alternate" type="text/html"></link>
    <summary type="text">Today I was combing through Nextcloud, just taking a gander at the apps, updates, etc.</summary>
    <content type="html">&lt;h1 id=&#34;intro&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Intro&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;Today I was combing through Nextcloud, just taking a gander at the apps, updates, etc.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The OPcache buffer is nearly full. To assure that all scripts can be hold in&#xA;cache, it is recommended to apply &amp;ldquo;opcache.memory_consumption&amp;rdquo; to your PHP&#xA;configuration with a value higher than &amp;ldquo;128&amp;rdquo;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;So I know &lt;em&gt;nothing&lt;/em&gt; about &lt;code&gt;php&lt;/code&gt; and I had no idea where to set this&amp;hellip; Also I&amp;rsquo;m&#xA;running Nextcloud in a container so any updates will be blown away when the&#xA;container is removed (say next time I update Nextcloud)&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;After a little duckduckgoing I came across &lt;a href=&#34;https://www.reddit.com/r/NextCloud/comments/1gpxl5b/need_help_with_php_opcache_module_warning/&#34;&gt;this reddit&#xA;post&lt;/a&gt;&#xA;where a guy had the same issue&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;The long and short of it is that on &lt;em&gt;single instance nextcloud deployments&lt;/em&gt;&#xA;this php memory consumption value can be too low for Nextcloud to keep up with&#xA;the demand&amp;hellip; You can see in the message they just recommend upping the value.&lt;/p&gt;&#xA;&lt;p&gt;So I had to think about how to persist the change and have it take effect now&#xA;ideally without affecting any users too much&amp;hellip; So here&amp;rsquo;s what I did - made the&#xA;change in 2 places:&lt;/p&gt;&#xA;&lt;h2 id=&#34;in-the-container&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;In the container&lt;/span&gt; &lt;a href=&#34;#in-the-container&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I exec&amp;rsquo;d into the container and used this handy &lt;code&gt;sed&lt;/code&gt; command &lt;code&gt;sed -i &#39;s/^opcache\.memory_consumption\s*=\s*128$/opcache.memory_consumption=256/&#39; /usr/local/etc/php/conf.d/opcache-recommended.ini&lt;/code&gt; to update the value in the&#xA;running container - and I guess &lt;code&gt;php&lt;/code&gt; maybe is loaded up dynamically or&#xA;something? but the warning did go away&amp;hellip;.&lt;/p&gt;&#xA;&lt;p&gt;So how to persist this change when the filesystem is blown away when the&#xA;container is updated?&lt;/p&gt;&#xA;&lt;h2 id=&#34;in-the-config&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;In the config&lt;/span&gt; &lt;a href=&#34;#in-the-config&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I set the env var &lt;code&gt;PHP_OPCACHE_MEMORY_CONSUMPTION&lt;/code&gt; in the &lt;code&gt;docker-compose.yml&lt;/code&gt;&#xA;file to 256 and voila&amp;hellip; the change should persist&amp;hellip;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Quit issueing 200s for 500s</title>
    <id>https://pype.dev/quit-issueing-200s-for-500s/</id>
    <updated>2025-06-22T06:55:21Z</updated>
    <published>2025-06-22T06:55:21Z</published>
    <link href="https://pype.dev/quit-issueing-200s-for-500s/" rel="alternate" type="text/html"></link>
    <content type="html">&lt;h1 id=&#34;stop-this-nonsense&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Stop this nonsense&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250622115500_5bd3bc21.png&#34; alt=&#34;20250622115500_5bd3bc21.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>💭 matduggan.com/what-would-a-kubernetes-2-0-look-like/</title>
    <id>https://pype.dev/thoughts-710/</id>
    <updated>2025-06-20T11:53:33Z</updated>
    <published>2025-06-20T11:53:33Z</published>
    <link href="https://pype.dev/thoughts-710/" rel="alternate" type="text/html"></link>
    <summary type="text">This article was longer than I had time to really consume but a heading caught my eye that I wanted to agree with - the</summary>
    <content type="text">&#xA;&lt;a href=&#34;https://matduggan.com/what-would-a-kubernetes-2-0-look-like/&#34;&gt;&#xA;    &lt;img&#xA;        src=&#34;https://shots.wayl.one/shot/?url=https://matduggan.com/what-would-a-kubernetes-2-0-look-like/&amp;height=450&amp;width=800&amp;scaled_width=800&amp;scaled_height=450&amp;selectors=&#34;&#xA;        alt=&#34;shot of post - matduggan.com/what-would-a-kubernetes-2-0-look-like/&#34;&#xA;        height=450&#xA;        width=800&#xA;    &gt;&#xA;&lt;/a&gt;&#xA;&#xA;Here&#39;s my thought on &lt;a href=&#34;https://matduggan.com/what-would-a-kubernetes-2-0-look-like/&#34;&gt;matduggan.com/what-would-a-kubernetes-2-0-look-like/&lt;/a&gt;&#xA;&#xA;---&#xA;&#xA;This article was longer than I had time to really consume but a heading caught my eye that I wanted to agree with - the author says k8s 2.0 may consider HCL instead of YAML. And as a recent terraform / open-tofu adopter I gotta say I would be ALL FOR THIS&#xA;&#xA;---&#xA;&#xA;!!! note&#xA;    This is one of [[ my-thoughts ]]. I picked this up from [Waylon Walker](https://waylonwalker.com)(https://thoughts.waylonwalker.com). It&#39;s a short note that I make about someone else&#39;s content online.  Learn more about the process [[ thoughts ]]&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Thinking In Diagrams</title>
    <id>https://pype.dev/thinking-in-diagrams/</id>
    <updated>2025-06-20T06:55:31Z</updated>
    <published>2025-06-20T06:55:31Z</published>
    <link href="https://pype.dev/thinking-in-diagrams/" rel="alternate" type="text/html"></link>
    <summary type="text">Something I didn&#39;t appreciate earlier on in my career (and I&#39;m only 8 as far as the age of that career goes anyways) was thinking through problems with...</summary>
    <content type="text">&#xA;# Intro&#xA;&#xA;Something I didn&#39;t appreciate earlier on in my career (and I&#39;m only 8 as far as&#xA;the age of that career goes anyways) was thinking through problems with&#xA;diagrams... I&#39;ve often approached a problem with code first, and immediately&#xA;started implementing a solution. There&#39;s nothing actually wrong with that especially when considering:&#xA;&#xA;1. people think differently&#xA;2. some people think with their fingers&#xA;3. recognizing that the first thing you build should be thrown away should give you freedom to &#34;just start&#34;&#xA;&#xA;Now with that said, let&#39;s chat about how awesome diagrams are though...&#xA;&#xA;1. they put context in front of you without details&#xA;2. you can express many more components of a system in a consumable way when compared to code&#xA;3. diagrams help prioritize work and bubble up maybe unforseen dependencies&#xA;4. they force you to wireframe before getting lost in the details&#xA;&#xA;## Wireframing&#xA;&#xA;One of my biggest issue when I &#34;just start coding&#34; is not having a direction...&#xA;I can put a few place holders `def this:` `def that:` in a few python modules,&#xA;but without having every place holder in front of me it is hard to keep them&#xA;straight, know the order or dependencies, etc.&#xA;&#xA;Diagrams aren&#39;t beholden to a text file or series of them, and you can fit much&#xA;more on your screen because you have all the X-Y available to you instead of&#xA;the height of your monitor times your formatted lined length (usually 120 for&#xA;me).&#xA;&#xA;Diagrams also make it easy to spew out onto a page the different components you&#xA;need for a solution, without committing to an order (something that I cannot&#xA;express well in scripts)&#xA;&#xA;## A Plan&#xA;&#xA;Diagramming with purpose can get you to the place of having almost a&#xA;paint-by-number experience building your app/system/etc. Beecause you separate&#xA;the implemetation from the design and when you implement BASED on a design&#xA;rather than implement to DISCOVER a design you will be more efficient and in my&#xA;experience I&#39;ve improved my ability to forsee issues that I wouldn&#39;t have seen,&#xA;or have historically missed, by putting the design down in front of me, the&#xA;details of any integrations, etc. before starting to &#34;just code&#34;.&#xA;&#xA;## Good Enough&#xA;&#xA;A final note about diagrams for right now is that they&#39;re easy to leave as&#xA;&#34;good enough&#34;. The point was to get a guide for solving a problem.&#xA;&#xA;Diagrams don&#39;t have to be picture perfect, even for documentation&#39;s sake. They&#xA;can even remain somewhat unfinished (permitted you don&#39;t get yourself into a&#xA;bind of treating diagrams as docs that you didn&#39;t clean up)&#xA;&#xA;Here&#39;s an example of what I mean - I&#39;m working on a simple workflow to take [my-thoughts](/my-thoughts) and post them to [[nostr]]. I started with a diagram like this...&#xA;&#xA;![20250622112223_f1838d9b.png](https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250622112223_f1838d9b.png)&#xA;&#xA;&gt; In parallel I&#39;m working on posting my blog to other social media - this small&#xA;&gt; workflow is apart of a larger initiative I&#39;m working on at home&#xA;&#xA;AS you can see this diagram isn&#39;t super detailed or pretty. But what it does it&#xA;help me see the high level points of bringing my published thoughts to nostr as&#xA;posts.&#xA;&#xA;After I have the simple steps, I&#39;ve started diagramming out more details of each step:&#xA;&#xA;![20250622112415_f18663e3.png](https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250622112415_f18663e3.png)&#xA;&#xA;The diagram is easy to put notes on, add some color to for problems not yet solved, etc.&#xA;&#xA;And then with this diagram in front of me, it&#39;s easy to begin building&#xA;small-scoped components that will be assembled to my larger system, but without&#xA;the pressure of constructing every part of the system at once&#xA;&#xA;# Fin&#xA;&#xA;Diagrams help me break up a problem into manageable chunks so that I can put&#xA;the things I need later on the back-burner and can focus on one achievable&#xA;thing at a time.&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>💭 pypeaday/whose-turn-is-it: Simple uv webapp to determine order…</title>
    <id>https://pype.dev/thoughts-709/</id>
    <updated>2025-06-20T01:23:26Z</updated>
    <published>2025-06-20T01:23:26Z</published>
    <link href="https://pype.dev/thoughts-709/" rel="alternate" type="text/html"></link>
    <summary type="text">We pray together as a family every night, but every single flipping night my daughter&#39;s fight about the order we go in..</summary>
    <content type="text">&#xA;&lt;a href=&#34;https://github.com/pypeaday/whose-turn-is-it&#34;&gt;&#xA;    &lt;img&#xA;        src=&#34;https://shots.wayl.one/shot/?url=https://github.com/pypeaday/whose-turn-is-it&amp;height=450&amp;width=800&amp;scaled_width=800&amp;scaled_height=450&amp;selectors=&#34;&#xA;        alt=&#34;shot of post - pypeaday/whose-turn-is-it: Simple uv webapp to determine order fo players for an event&#34;&#xA;        height=450&#xA;        width=800&#xA;    &gt;&#xA;&lt;/a&gt;&#xA;&#xA;Here&#39;s my thought on &lt;a href=&#34;https://github.com/pypeaday/whose-turn-is-it&#34;&gt;pypeaday/whose-turn-is-it: Simple uv webapp to determine order fo players for an event&lt;/a&gt;&#xA;&#xA;---&#xA;&#xA;We pray together as a family every night, but every single flipping night my daughter&#39;s fight about the order we go in... well, NO MORE!&#xA;&#xA;I built a simple uv fastapi app that randomly sorts a list from an environment var `PLAYERS` and presents it in the web page at `/generate`.&#xA;&#xA;Super easy `uv run` at home...&#xA;&#xA;I love that with enough knowledge, or the right kind of knowledge, you can build like anything you want!&#xA;&#xA;---&#xA;&#xA;!!! note&#xA;    This is one of [[ my-thoughts ]]. I picked this up from [Waylon Walker](https://waylonwalker.com)(https://thoughts.waylonwalker.com). It&#39;s a short note that I make about someone else&#39;s content online.  Learn more about the process [[ thoughts ]]&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>💭 Microsoft planning thousands of job cuts aimed at salespeople,…</title>
    <id>https://pype.dev/thoughts-707/</id>
    <updated>2025-06-19T10:51:59Z</updated>
    <published>2025-06-19T10:51:59Z</published>
    <link href="https://pype.dev/thoughts-707/" rel="alternate" type="text/html"></link>
    <summary type="text">more cuts for the sake of AI investment... this is getting out of hand. I&#39;m thankful that I don&#39;t work in a field that w</summary>
    <content type="text">&#xA;&lt;a href=&#34;https://www.reuters.com/business/world-at-work/microsoft-planning-thousands-job-cuts-aimed-salespeople-bloomberg-news-reports-2025-06-18/&#34;&gt;&#xA;    &lt;img&#xA;        src=&#34;https://shots.wayl.one/shot/?url=https://www.reuters.com/business/world-at-work/microsoft-planning-thousands-job-cuts-aimed-salespeople-bloomberg-news-reports-2025-06-18/&amp;height=450&amp;width=800&amp;scaled_width=800&amp;scaled_height=450&amp;selectors=&#34;&#xA;        alt=&#34;shot of post - Microsoft planning thousands of job cuts aimed at salespeople, Bloomberg News reports | Reuters&#34;&#xA;        height=450&#xA;        width=800&#xA;    &gt;&#xA;&lt;/a&gt;&#xA;&#xA;Here&#39;s my thought on &lt;a href=&#34;https://www.reuters.com/business/world-at-work/microsoft-planning-thousands-job-cuts-aimed-salespeople-bloomberg-news-reports-2025-06-18/&#34;&gt;Microsoft planning thousands of job cuts aimed at salespeople, Bloomberg News reports | Reuters&lt;/a&gt;&#xA;&#xA;---&#xA;&#xA;more cuts for the sake of AI investment... this is getting out of hand. I&#39;m thankful that I don&#39;t work in a field that will be overtaken by AI in the sense of losing my job (I mean we&#39;re like 47 months into AI will end dev jobs tomorrow) - of course I have to learn about the tools and LLMs have increased my output in many ways. If I was fearful of losing my job, for example being in Sales at Microsoft, I would be using every on-the-clock hour to find a new job...&#xA;&#xA;---&#xA;&#xA;!!! note&#xA;    This is one of [[ my-thoughts ]]. I picked this up from [Waylon Walker](https://waylonwalker.com)(https://thoughts.waylonwalker.com). It&#39;s a short note that I make about someone else&#39;s content online.  Learn more about the process [[ thoughts ]]&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Homelab Youtube Podcasts to AudioBookShelf Pipeline</title>
    <id>https://pype.dev/homelab-youtube-podcasts-to-audiobookshelf-pipeline/</id>
    <updated>2025-06-18T13:53:12Z</updated>
    <published>2025-06-18T13:53:12Z</published>
    <link href="https://pype.dev/homelab-youtube-podcasts-to-audiobookshelf-pipeline/" rel="alternate" type="text/html"></link>
    <summary type="text">I wrote about using homelab-pinchflat for at-home mashup creation and a song flow for church. But I use it for more than, that and here&#39;s another prime use case</summary>
    <content type="text">&#xA;I wrote about using [[homelab-pinchflat]] for at-home mashup creation and a song flow&#xA;for church. But I use it for more than, that and here&#39;s another prime use case&#xA;&#xA;There are podcasts on YouTube I want to follow - The Standup with Prime, or&#xA;Shawn Ryan&#39;s show. Basically I use pinchflat to download the audio and serve up&#xA;those files in ABS (audiobookshelf)&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>💭 neverjust</title>
    <id>https://pype.dev/thoughts-705/</id>
    <updated>2025-06-18T10:33:49Z</updated>
    <published>2025-06-18T10:33:49Z</published>
    <link href="https://pype.dev/thoughts-705/" rel="alternate" type="text/html"></link>
    <summary type="text">Your &#34;just&#34; comes from seeing only the surface of the problem. Like an iceberg, what&#39;s visible is just a fraction This</summary>
    <content type="text">&#xA;&lt;a href=&#34;https://www.neverjust.net/&#34;&gt;&#xA;    &lt;img&#xA;        src=&#34;https://shots.wayl.one/shot/?url=https://www.neverjust.net/&amp;height=450&amp;width=800&amp;scaled_width=800&amp;scaled_height=450&amp;selectors=&#34;&#xA;        alt=&#34;shot of post - neverjust&#34;&#xA;        height=450&#xA;        width=800&#xA;    &gt;&#xA;&lt;/a&gt;&#xA;&#xA;Here&#39;s my thought on &lt;a href=&#34;https://www.neverjust.net/&#34;&gt;neverjust&lt;/a&gt;&#xA;&#xA;---&#xA;&#xA;Your &#34;just&#34; comes from seeing only the surface of the problem. Like an iceberg, what&#39;s visible is just a fraction&#xA;&#xA;This is a good reminder when discussing issues within a team or with your buddies... trivializing someone else&#39;s problem, in tech or out, it not a good look&#xA;&#xA;---&#xA;&#xA;!!! note&#xA;    This is one of [[ my-thoughts ]]. I picked this up from [Waylon Walker](https://waylonwalker.com)(https://thoughts.waylonwalker.com). It&#39;s a short note that I make about someone else&#39;s content online.  Learn more about the process [[ thoughts ]]&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>source_up for nested .envrc</title>
    <id>https://pype.dev/source-up-for-nested-envrc/</id>
    <updated>2025-06-17T09:52:17Z</updated>
    <published>2025-06-17T09:52:17Z</published>
    <link href="https://pype.dev/source-up-for-nested-envrc/" rel="alternate" type="text/html"></link>
    <summary type="text">I have a use case for nesting directories with cascading .envrc files. and ran into an issue where the parent environment was being reset by the child...</summary>
    <content type="html">&lt;h1 id=&#34;tldr&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;TLDR&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;I have a use case for nesting directories with cascading .envrc files. and ran&#xA;into an issue where the parent environment was being reset by the child&#xA;environment. The fix is &lt;code&gt;source_up&lt;/code&gt;&lt;/p&gt;&#xA;&lt;h1 id=&#34;context&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Context&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;I manage some infrastructure at home with a folder like this:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── homelab&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── .envrc&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   └── stack1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│       ├── .envrc&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I do this so that the &amp;ldquo;homelab-wide&amp;rdquo; terraform variables can be exported with&#xA;&lt;code&gt;TF_VAR_the_variable&lt;/code&gt; in the &lt;code&gt;homelab/.envrc&lt;/code&gt; and then the stack specific&#xA;variables in &lt;code&gt;stack1/.envrc&lt;/code&gt; get exported like &lt;code&gt;TF_VAR_stack_specific_var&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;For example, my cloudflare account id is needed in every stack, but the&#xA;cloudflare zone id is different per stack - so instead of copying the account&#xA;id var to every stack (however the vars are managed), I can set it in a parent&#xA;.envrc and share it in nested stack directories&lt;/p&gt;&#xA;&lt;h2 id=&#34;problem&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Problem&lt;/span&gt; &lt;a href=&#34;#problem&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;pre&gt;&lt;code&gt;# homelab/.envrc&#xA;#!/bin/bash&#xA;export VAR_FOO=BAR&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;So when I &lt;code&gt;cd homelab&lt;/code&gt; I get&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;nic in /tmp/homelab   (dev) 󰒄 󱔎 NO PYTHON ENVIORNMENT SET&#xA;⬢ [devbox] ❯ direnv allow&#xA;direnv: loading /tmp/homelab/.envrc&#xA;direnv: export +VAR_FOO&#xA;&#xA;nic in /tmp/homelab   (dev) 󰒄 󱔎 NO PYTHON ENVIORNMENT SET&#xA;⬢ [devbox] ❯ env | grep VAR&#xA;VAR_FOO=BAR&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;You can see &lt;code&gt;VAR_FOO&lt;/code&gt; is set&amp;hellip; but now I&amp;rsquo;ll &lt;code&gt;cd stack1&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;nic in /tmp/homelab   (dev) 󰒄 󱔎 NO PYTHON ENVIORNMENT SET&#xA;⬢ [devbox] ❯ cd stack1&#xA;direnv: error /tmp/homelab/stack1/.envrc is blocked. Run `direnv allow` to approve its content&#xA;&#xA;nic in /tmp/homelab/stack1   (dev) 󰒄 󱔎 NO PYTHON ENVIORNMENT SET&#xA;⬢ [devbox] ❯ direnv allow&#xA;direnv: loading /tmp/homelab/stack1/.envrc&#xA;direnv: export +VAR_BAZ&#xA;&#xA;nic in /tmp/homelab/stack1   (dev) 󰒄 󱔎 NO PYTHON ENVIORNMENT SET&#xA;⬢ [devbox] ❯ env | grep VAR&#xA;VAR_BAZ=BAM&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;As you can see &lt;code&gt;VAR_FOO&lt;/code&gt; was unset, and &lt;code&gt;VAR_BAZ&lt;/code&gt; is set&amp;hellip; so &lt;code&gt;homelab/.envrc&lt;/code&gt; was blown away!&lt;/p&gt;&#xA;&lt;h2 id=&#34;fix&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Fix&lt;/span&gt; &lt;a href=&#34;#fix&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Edit &lt;code&gt;stack1/.envrc&lt;/code&gt; with a &lt;code&gt;source_up&lt;/code&gt; command&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;# stack1/.envrc # NEW&#xA;#!/bin/bash&#xA;source_up  # source the parent environment&#xA;export VAR_BAZ=BAM&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;After the edit&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;nic in /tmp/homelab/stack1   (dev) 󰒄 󱔎 NO PYTHON ENVIORNMENT SET&#xA;⬢ [devbox] ❯ vim .envrc&#xA;direnv: error /tmp/homelab/stack1/.envrc is blocked. Run `direnv allow` to approve its content&#xA;&#xA;nic in /tmp/homelab/stack1   (dev) 󰒄 󱔎 NO PYTHON ENVIORNMENT SET  took 5s&#xA;⬢ [devbox] ❯ direnv allow&#xA;direnv: loading /tmp/homelab/stack1/.envrc&#xA;direnv: loading /tmp/homelab/.envrc&#xA;direnv: export +VAR_BAZ +VAR_FOO&#xA;&#xA;nic in /tmp/homelab/stack1   (dev) 󰒄 󱔎 NO PYTHON ENVIORNMENT SET&#xA;⬢ [devbox] ❯ env | grep VAR&#xA;VAR_FOO=BAR&#xA;VAR_BAZ=BAM&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Both vars are set!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Stable Diffusion QR Codes for Josh</title>
    <id>https://pype.dev/stable-diffusion-qr-codes-for-josh/</id>
    <updated>2025-06-17T06:27:28Z</updated>
    <published>2025-06-17T06:27:28Z</published>
    <link href="https://pype.dev/stable-diffusion-qr-codes-for-josh/" rel="alternate" type="text/html"></link>
    <summary type="text">(fjords of Finland:1.3), (steep cliffs:1.1), (crystal-clear water:1.2), (reflection of sky on water:1.1), (early morning light:1.2), (golden hour glow:1.1),...</summary>
    <content type="html">&lt;h1 id=&#34;after-my-blunder&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;After my blunder&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250627111955_e86d5db2.png&#34; alt=&#34;20250627111955_e86d5db2.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;(fjords of Finland:1.3), (steep cliffs:1.1), (crystal-clear water:1.2), (reflection of sky on water:1.1), (early morning light:1.2), (golden hour glow:1.1), (pine trees:1.1),(serene nature:1.2), (8K landscape photography:1.3), (gaming concept art:1.2), (ultra realistic: 1.2)&lt;/p&gt;&#xA;&lt;p&gt;Negative prompt: (blurry:1.3), (low resolution:1.3), (overexposed:1.2), (cartoonish:1.3), (unrealistic colors:1.3), (people:1.1),y&#xA;Steps: 30, Sampler: Euler a, Schedule type: Automatic, CFG scale: 7, Seed: 784129766, Size: 1536x1536, Model hash: 4199bcdd14, Model: revAnimated_v122EOL, ControlNet 0: &amp;ldquo;Module: none, Model: control_v1p_sd15_brightness [5f6aa6ed], Weight: 0.25, Resize Mode: Crop and Resize, Processor Res: 512, Threshold A: 0.5, Threshold B: 0.5, Guidance Start: 0.25, Guidance End: 0.8, Pixel Perfect: True, Control Mode: Balanced&amp;rdquo;, ControlNet 1: &amp;ldquo;Module: none, Model: control_v1p_sd15_brightness [5f6aa6ed], Weight: 0.25, Resize Mode: Crop and Resize, Processor Res: 512, Threshold A: 0.5, Threshold B: 0.5, Guidance Start: 0.25, Guidance End: 0.75, Pixel Perfect: True, Control Mode: Balanced&amp;rdquo;, Version: v1.9.4&lt;/p&gt;&#xA;&lt;h1 id=&#34;final-candidates&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Final Candidates&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;Turns out upscaling can mess up the design&amp;hellip; so I generated new ones at the high res instead of using AI to upscale&lt;/p&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250621122040_2dfef68f.png&#34; alt=&#34;20250621122040_2dfef68f.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;(fjords of Finland:1.3), (steep cliffs:1.1), (crystal-clear water:1.2), (reflection of sky on water:1.1), (early morning light:1.2), (golden hour glow:1.1), (pine trees:1.1),(serene nature:1.2), (8K landscape photography:1.3), (gaming concept art:1.2), (ultra realistic: 1.2)&lt;/p&gt;&#xA;&lt;p&gt;Negative prompt: (blurry:1.3), (low resolution:1.3), (overexposed:1.2), (cartoonish:1.3), (unrealistic colors:1.3), (people:1.1), (city buildings:1.2), (vehicles:1.2), (text:1.3), (distortion:1.2)&lt;/p&gt;&#xA;&lt;p&gt;Steps: 30, Sampler: Euler a, Schedule type: Automatic, CFG scale: 7, Seed: 1827707865, Size: 1536x1536, Model hash: 4199bcdd14, Model: revAnimated_v122EOL, ControlNet 0: &amp;ldquo;Module: none, Model: control_v1p_sd15_brightness [5f6aa6ed], Weight: 0.25, Resize Mode: Crop and Resize, Processor Res: 1536, Threshold A: 0.5, Threshold B: 0.5, Guidance Start: 0.25, Guidance End: 1.0, Pixel Perfect: False, Control Mode: Balanced&amp;rdquo;, ControlNet 1: &amp;ldquo;Module: none, Model: control_v1p_sd15_brightness [5f6aa6ed], Weight: 0.25, Resize Mode: Crop and Resize, Processor Res: 512, Threshold A: 0.5, Threshold B: 0.5, Guidance Start: 0.25, Guidance End: 0.88, Pixel Perfect: False, Control Mode: Balanced&amp;rdquo;, Version: v1.9.4&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;p&gt;I turned the brightness down on the above one a little and got a better result&lt;/p&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250621122629_1058a54f.png&#34; alt=&#34;20250621122629_1058a54f.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;(fjords of Finland:1.3), (steep cliffs:1.1), (crystal-clear water:1.2), (reflection of sky on water:1.1), (early morning light:1.2), (golden hour glow:1.1), (pine trees:1.1),(serene nature:1.2), (8K landscape photography:1.3), (gaming concept art:1.2), (ultra realistic: 1.2)&lt;/p&gt;&#xA;&lt;p&gt;Negative prompt: (blurry:1.3), (low resolution:1.3), (overexposed:1.2), (cartoonish:1.3), (unrealistic colors:1.3), (people:1.1), (city buildings:1.2), (vehicles:1.2), (text:1.3), (distortion:1.2)&lt;/p&gt;&#xA;&lt;p&gt;Steps: 30, Sampler: Euler a, Schedule type: Automatic, CFG scale: 7, Seed: 1827707865, Size: 1536x1536, Model hash: 4199bcdd14, Model: revAnimated_v122EOL, ControlNet 0: &amp;ldquo;Module: none, Model: control_v1p_sd15_brightness [5f6aa6ed], Weight: 0.25, Resize Mode: Crop and Resize, Processor Res: 1536, Threshold A: 0.5, Threshold B: 0.5, Guidance Start: 0.25, Guidance End: 0.85, Pixel Perfect: False, Control Mode: Balanced&amp;rdquo;, ControlNet 1: &amp;ldquo;Module: none, Model: control_v1p_sd15_brightness [5f6aa6ed], Weight: 0.25, Resize Mode: Crop and Resize, Processor Res: 512, Threshold A: 0.5, Threshold B: 0.5, Guidance Start: 0.25, Guidance End: 0.75, Pixel Perfect: False, Control Mode: Balanced&amp;rdquo;, Version: v1.9.4&lt;/p&gt;&#xA;&lt;h1 id=&#34;some-favorites&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Some favorites&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250621020431_d6c69cd2.png&#34; alt=&#34;20250621020431_d6c69cd2.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;(fjords of Finland:1.3), (steep cliffs:1.1), (crystal-clear water:1.2), (reflection of sky on water:1.1), (early morning light:1.2), (golden hour glow:1.1), (pine trees:1.1), (green orange:1.0), (serene nature:1.2), (8K landscape photography:1.3), (gaming concept art:1.2), (ultra realistic: 1.1)&lt;/p&gt;&#xA;&lt;p&gt;Negative prompt: (blurry:1.3), (low resolution:1.3), (overexposed:1.2), (cartoonish:1.3), (unrealistic colors:1.3), (people:1.1), (city buildings:1.2), (vehicles:1.2), (text:1.3), (distortion:1.2)&lt;/p&gt;&#xA;&lt;p&gt;Steps: 30, Sampler: Euler a, Schedule type: Automatic, CFG scale: 7, Seed: 2926433856, Size: 768x768, Model hash: 4199bcdd14, Model: revAnimated_v122EOL, ControlNet 0: &amp;ldquo;Module: none, Model: control_v1p_sd15_brightness [5f6aa6ed], Weight: 0.25, Resize Mode: Crop and Resize, Processor Res: 512, Threshold A: 0.5, Threshold B: 0.5, Guidance Start: 0.25, Guidance End: 1.0, Pixel Perfect: False, Control Mode: Balanced&amp;rdquo;, ControlNet 1: &amp;ldquo;Module: none, Model: control_v1p_sd15_brightness [5f6aa6ed], Weight: 0.25, Resize Mode: Crop and Resize, Processor Res: 512, Threshold A: 0.5, Threshold B: 0.5, Guidance Start: 0.25, Guidance End: 0.85, Pixel Perfect: False, Control Mode: Balanced&amp;rdquo;, Version: v1.9.4&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250621020700_37cf8c79.png&#34; alt=&#34;20250621020700_37cf8c79.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;(fjords of Finland:1.3), (steep cliffs:1.1), (crystal-clear water:1.2), (reflection of sky on water:1.1), (early morning light:1.2), (golden hour glow:1.1), (pine trees:1.1),(serene nature:1.2), (8K landscape photography:1.3), (gaming concept art:1.2), (ultra realistic: 1.2)&lt;/p&gt;&#xA;&lt;p&gt;Negative prompt: (blurry:1.3), (low resolution:1.3), (overexposed:1.2), (cartoonish:1.3), (unrealistic colors:1.3), (people:1.1), (city buildings:1.2), (vehicles:1.2), (text:1.3), (distortion:1.2)&lt;/p&gt;&#xA;&lt;p&gt;Steps: 30, Sampler: Euler a, Schedule type: Automatic, CFG scale: 7, Seed: 1827707865, Size: 768x768, Model hash: 4199bcdd14, Model: revAnimated_v122EOL, ControlNet 0: &amp;ldquo;Module: none, Model: control_v1p_sd15_brightness [5f6aa6ed], Weight: 0.25, Resize Mode: Crop and Resize, Processor Res: 512, Threshold A: 0.5, Threshold B: 0.5, Guidance Start: 0.25, Guidance End: 1.0, Pixel Perfect: False, Control Mode: Balanced&amp;rdquo;, ControlNet 1: &amp;ldquo;Module: none, Model: control_v1p_sd15_brightness [5f6aa6ed], Weight: 0.25, Resize Mode: Crop and Resize, Processor Res: 512, Threshold A: 0.5, Threshold B: 0.5, Guidance Start: 0.25, Guidance End: 0.88, Pixel Perfect: False, Control Mode: Balanced&amp;rdquo;, Version: v1.9.4&lt;/p&gt;&#xA;&lt;h1 id=&#34;codes-and-prompts&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Codes and prompts&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;hr&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250617112815_b986db88.png&#34; alt=&#34;20250617112815_b986db88.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;prompt: (breathtaking scenic view:1.2), (fjords of Finland:1.3), (steep forested cliffs:1.1), (crystal-clear blue water:1.2), (reflection of sky on water:1.1), , (early morning light:1.2), (golden hour glow:1.1), (pine trees:1.1), (birch trees:1.0), (serene nature:1.2), (ultra-realistic:1.3), (8K landscape photography:1.3), (photorealistic:1.2), (atmospheric lighting:1.2)&lt;/p&gt;&#xA;&lt;p&gt;Negative prompt: (blurry:1.3), (low resolution:1.3), (overexposed:1.2), (cartoonish:1.3), (unrealistic colors:1.3), (people:1.1), (city buildings:1.2), (vehicles:1.2), (text:1.3), (distortion:1.2)&lt;/p&gt;&#xA;&lt;p&gt;Steps: 30, Sampler: DPM++ 2M SDE, Schedule type: Karras, CFG scale: 7, Seed: 2206746812, Size: 768x768, Model hash: 4199bcdd14, Model: revAnimated_v122EOL, ControlNet 0: &amp;ldquo;Module: none, Model: controlnetQRPatternQR_v2Sd15 [2d8d5750], Weight: 1.15, Resize Mode: Crop and Resize, Processor Res: 512, Threshold A: 0.5, Threshold B: 0.5, Guidance Start: 0.0, Guidance End: 0.85, Pixel Perfect: True, Control Mode: Balanced&amp;rdquo;, Version: v1.9.4&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250617113111_d9075159.png&#34; alt=&#34;20250617113111_d9075159.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;(breathtaking scenic view:1.2), (fjords of Finland:1.3), (steep forested cliffs:1.1), (crystal-clear water:1.2), (reflection of sky on water:1.1), , (early morning light:1.2), (golden hour glow:1.1), (pine trees:1.1), (birch trees:1.0), (serene nature:1.2), (ultra-realistic:1.3), (8K landscape photography:1.3), (photorealistic:1.2), (greens and blues:1.2)&lt;/p&gt;&#xA;&lt;p&gt;Negative prompt: (blurry:1.3), (low resolution:1.3), (overexposed:1.2), (cartoonish:1.3), (unrealistic colors:1.3), (people:1.1), (city buildings:1.2), (vehicles:1.2), (text:1.3), (distortion:1.2)&#xA;Steps: 30, Sampler: DPM++ 2M SDE, Schedule type: Karras, CFG scale: 7, Seed: 2485699904, Size: 768x768, Model hash: 4199bcdd14, Model: revAnimated_v122EOL, ControlNet 0: &amp;ldquo;Module: none, Model: controlnetQRPatternQR_v2Sd15 [2d8d5750], Weight: 1.1, Resize Mode: Crop and Resize, Processor Res: 512, Threshold A: 0.5, Threshold B: 0.5, Guidance Start: 0.0, Guidance End: 0.8, Pixel Perfect: True, Control Mode: Balanced&amp;rdquo;, Version: v1.9.4&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250617113250_839c12e2.png&#34; alt=&#34;20250617113250_839c12e2.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;(breathtaking scenic view:1.2), (fjord:1.3), (steep forested cliffs:1.1), (crystal-clear water:1.2), (reflection of sky on water:1.1), , (early morning light:1.2), (golden hour glow:1.1), (pine trees:1.1), (birch trees:1.0), (serene nature:1.2), (ultra-realistic:1.3), (8K landscape photography:1.3), (photorealistic:1.2), (green:1.2)&lt;/p&gt;&#xA;&lt;p&gt;Negative prompt: (blurry:1.3), (low resolution:1.3), (overexposed:1.2), (cartoonish:1.3), (unrealistic colors:1.3), (people:1.1), (city buildings:1.2), (vehicles:1.2), (text:1.3), (distortion:1.2)&#xA;Steps: 30, Sampler: DPM++ 2M SDE, Schedule type: Karras, CFG scale: 8, Seed: 1055874558, Size: 768x768, Model hash: 4199bcdd14, Model: revAnimated_v122EOL, ControlNet 0: &amp;ldquo;Module: none, Model: controlnetQRPatternQR_v2Sd15 [2d8d5750], Weight: 1.1, Resize Mode: Crop and Resize, Processor Res: 512, Threshold A: 0.5, Threshold B: 0.5, Guidance Start: 0.0, Guidance End: 0.8, Pixel Perfect: True, Control Mode: Balanced&amp;rdquo;, Version: v1.9.4&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;top-contendor&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Top Contendor&lt;/span&gt; &lt;a href=&#34;#top-contendor&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250618005414_d77ff449.png&#34; alt=&#34;20250618005414_d77ff449.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;(breathtaking scenic view:1.2), (fjords of Finland:1.3), (steep forested cliffs:1.1), (crystal-clear water:1.2), (reflection of sky on water:1.1), , (early morning light:1.2), (golden hour glow:1.1), (pine trees:1.1), (green orange:1.0), (serene nature:1.2), (ultra-realistic:1.3), (8K landscape photography:1.3), (gaming concept art:1.2),&lt;/p&gt;&#xA;&lt;p&gt;Negative prompt: (blurry:1.3), (low resolution:1.3), (overexposed:1.2), (cartoonish:1.3), (unrealistic colors:1.3), (people:1.1), (city buildings:1.2), (vehicles:1.2), (text:1.3), (distortion:1.2)&lt;/p&gt;&#xA;&lt;p&gt;Steps: 30, Sampler: DPM++ 2M SDE, Schedule type: Karras, CFG scale: 8.5, Seed: 1240242415, Size: 768x768, Model hash: 4199bcdd14, Model: revAnimated_v122EOL, ControlNet 0: &amp;ldquo;Module: none, Model: controlnetQRPatternQR_v2Sd15 [2d8d5750], Weight: 1.1, Resize Mode: Crop and Resize, Processor Res: 512, Threshold A: 0.5, Threshold B: 0.5, Guidance Start: 0.0, Guidance End: 0.8, Pixel Perfect: False, Control Mode: Balanced&amp;rdquo;, Version: v1.9.4&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250618005451_84cd9350.png&#34; alt=&#34;20250618005451_84cd9350.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;(breathtaking scenic view:1.2), (fjords of Finland:1.3), (steep forested cliffs:1.1), (crystal-clear water:1.2), (reflection of sky on water:1.1), , (early morning light:1.2), (golden hour glow:1.1), (pine trees:1.1), (green orange:1.0), (serene nature:1.2), (ultra-realistic:1.3), (8K landscape photography:1.3), (gaming concept art:1.2),&lt;/p&gt;&#xA;&lt;p&gt;Negative prompt: (blurry:1.3), (low resolution:1.3), (overexposed:1.2), (cartoonish:1.3), (unrealistic colors:1.3), (people:1.1), (city buildings:1.2), (vehicles:1.2), (text:1.3), (distortion:1.2)&lt;/p&gt;&#xA;&lt;p&gt;Steps: 30, Sampler: DPM++ 2M SDE, Schedule type: Karras, CFG scale: 8.5, Seed: 1240242416, Size: 768x768, Model hash: 4199bcdd14, Model: revAnimated_v122EOL, ControlNet 0: &amp;ldquo;Module: none, Model: controlnetQRPatternQR_v2Sd15 [2d8d5750], Weight: 1.1, Resize Mode: Crop and Resize, Processor Res: 512, Threshold A: 0.5, Threshold B: 0.5, Guidance Start: 0.0, Guidance End: 0.8, Pixel Perfect: False, Control Mode: Balanced&amp;rdquo;, Version: v1.9.4&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;p&gt;Scans!&lt;/p&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250621004622_6c9a66df.png&#34; alt=&#34;20250621004622_6c9a66df.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;(fjords of Finland:1.3), (steep forested cliffs:1.1), (crystal-clear water:1.2), (reflection of sky on water:1.1), , (early morning light:1.2), (golden hour glow:1.1), (pine trees:1.1), (green orange:1.0), (serene nature:1.2), (8K landscape photography:1.3), (gaming concept art:1.2),&lt;/p&gt;&#xA;&lt;p&gt;(blurry:1.3), (low resolution:1.3), (overexposed:1.2), (cartoonish:1.3), (unrealistic colors:1.3), (people:1.1), (city buildings:1.2), (vehicles:1.2), (text:1.3), (distortion:1.2)&lt;/p&gt;&#xA;&lt;p&gt;Steps: 30, Sampler: DPM++ 2M SDE, Schedule type: Exponential, CFG scale: 7, Seed: 4060643233, Size: 768x768, Model hash: 4199bcdd14, Model: revAnimated_v122EOL, ControlNet 0: &amp;ldquo;Module: none, Model: controlnetQRPatternQR_v2Sd15 [2d8d5750], Weight: 1.4, Resize Mode: Crop and Resize, Processor Res: 512, Threshold A: 0.5, Threshold B: 0.5, Guidance Start: 0.0, Guidance End: 0.8, Pixel Perfect: True, Control Mode: Balanced&amp;rdquo;, Version: v1.9.4&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250621004844_64e6b94b.png&#34; alt=&#34;20250621004844_64e6b94b.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;(fjords of Finland:1.3), (steep forested cliffs:1.1), (crystal-clear water:1.2), (reflection of sky on water:1.1), , (early morning light:1.2), (golden hour glow:1.1), (pine trees:1.1), (green blue:1.0), (serene nature:1.2), (8K landscape photography:1.3), (gaming concept art:1.2),&lt;/p&gt;&#xA;&lt;p&gt;Negative prompt: (blurry:1.3), (low resolution:1.3), (overexposed:1.2), (cartoonish:1.3), (unrealistic colors:1.3), (people:1.1), (city buildings:1.2), (vehicles:1.2), (text:1.3), (distortion:1.2)&lt;/p&gt;&#xA;&lt;p&gt;Steps: 30, Sampler: DPM++ 2M SDE, Schedule type: Exponential, CFG scale: 7, Seed: 3713594572, Size: 768x768, Model hash: 4199bcdd14, Model: revAnimated_v122EOL, ControlNet 0: &amp;ldquo;Module: none, Model: controlnetQRPatternQR_v2Sd15 [2d8d5750], Weight: 1.4, Resize Mode: Crop and Resize, Processor Res: 512, Threshold A: 0.5, Threshold B: 0.5, Guidance Start: 0.0, Guidance End: 0.8, Pixel Perfect: True, Control Mode: Balanced&amp;rdquo;, Version: v1.9.4&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>💭 Snowflake Status - Certificate Authority Update for AWS Regions</title>
    <id>https://pype.dev/thoughts-698/</id>
    <updated>2025-06-16T16:37:12Z</updated>
    <published>2025-06-16T16:37:12Z</published>
    <link href="https://pype.dev/thoughts-698/" rel="alternate" type="text/html"></link>
    <summary type="text">A recent Snowflake issue borked some old pipelines - thankfully it appears to be a simple fix. Just goes to show you tha</summary>
    <content type="text">&#xA;&lt;a href=&#34;https://status.snowflake.com/incidents/txclg2cyzq32&#34;&gt;&#xA;    &lt;img&#xA;        src=&#34;https://shots.wayl.one/shot/?url=https://status.snowflake.com/incidents/txclg2cyzq32&amp;height=450&amp;width=800&amp;scaled_width=800&amp;scaled_height=450&amp;selectors=&#34;&#xA;        alt=&#34;shot of post - Snowflake Status - Certificate Authority Update for AWS Regions&#34;&#xA;        height=450&#xA;        width=800&#xA;    &gt;&#xA;&lt;/a&gt;&#xA;&#xA;Here&#39;s my thought on &lt;a href=&#34;https://status.snowflake.com/incidents/txclg2cyzq32&#34;&gt;Snowflake Status - Certificate Authority Update for AWS Regions&lt;/a&gt;&#xA;&#xA;---&#xA;&#xA;A recent Snowflake issue borked some old pipelines - thankfully it appears to be a simple fix. Just goes to show you that you can&#39;t just deploy pipelines and expect them to live forever, they have to be maintained when there are ANY external dependencies&#xA;&#xA;---&#xA;&#xA;!!! note&#xA;    This is one of [[ my-thoughts ]]. I picked this up from [Waylon Walker](https://waylonwalker.com)(https://thoughts.waylonwalker.com). It&#39;s a short note that I make about someone else&#39;s content online.  Learn more about the process [[ thoughts ]]&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>U-Blue Aurora Upgrade Broke HWA Docker</title>
    <id>https://pype.dev/u-blue-aurora-upgrade-broke-hwa-docker/</id>
    <updated>2025-06-15T08:42:09Z</updated>
    <published>2025-06-15T08:42:09Z</published>
    <link href="https://pype.dev/u-blue-aurora-upgrade-broke-hwa-docker/" rel="alternate" type="text/html"></link>
    <summary type="text">I use Universal Blue&#39;s Aurora distribution on my daily driver desktop, and I rebooted today which led what I imagine is a kernel update. This broke all of my...</summary>
    <content type="html">&lt;p&gt;I use Universal Blue&amp;rsquo;s &lt;a href=&#34;https://getaurora.dev/en&#34;&gt;Aurora&lt;/a&gt; distribution on my daily driver desktop, and&#xA;I rebooted today which led what I imagine is a kernel update. This broke all of&#xA;my docker containers using a GPU.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;nvidia-container-cli: detection error: open failed: /usr/lib/libnvidia-tls.so.570.153.02: no such file or directory: unknown&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Thankfully a reboot and booting into the older environment fixes everything&amp;hellip;&#xA;Linux and immutability FTW&lt;/p&gt;&#xA;&lt;h2 id=&#34;related&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Related&lt;/span&gt; &lt;a href=&#34;#related&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://universal-blue.discourse.group/t/cannot-use-nvidia-runtime-in-docker-since-update-to-fedora-42/8812/3&#34;&gt;Discorse Thread&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Homelab Pinchflat</title>
    <id>https://pype.dev/homelab-pinchflat/</id>
    <updated>2025-06-14T08:51:21Z</updated>
    <published>2025-06-14T08:51:21Z</published>
    <link href="https://pype.dev/homelab-pinchflat/" rel="alternate" type="text/html"></link>
    <summary type="text">I&#39;ve written about self-hosted-media before and addressed some thoughts with YouTube.</summary>
    <content type="text">&#xA;# Why?&#xA;&#xA;I&#39;ve written about [[self-hosted-media]] before and addressed some thoughts with YouTube. &#xA;&#xA;Lately though I&#39;ve had 2 use cases for offline YouTube media and I&#39;m now&#xA;solving this problem by using [pinchflat](https://pinchflat.com/) as my `ytdl`&#xA;solution + file system organization for use throughout my homelab.&#xA;&#xA;## Use Case 1&#xA;&#xA;At church we use pre-recorded music to sing along to, or at least we used to,&#xA;thankfully as of June 2025 we&#39;re doing live-music every week. But in the before&#xA;times I would strip the audio out of song files we had purchased and then made&#xA;lyric videos with the instrumental tracks. As we wanted to try new songs out we&#xA;didn&#39;t want to purchase them in case they didn&#39;t work out for us to use and&#xA;that ends up being a waste (church budget is very tight). So using songs&#xA;available on YouTube is an easy solution, but the only way to strip the vocals&#xA;and see if the song sounded right with our singers and equipment was to make&#xA;the lyric video and rehearse it... Chicken or Egg problem unless we can freely&#xA;try it before purchasing... So using Pinchflat we can download songs in that&#xA;playlist, I can edit the files, the team can try it out, and if we like it we&#xA;can use it without hitting the budget any harder than necessary.&#xA;&#xA;&gt; Pinchflat syncs that playlist to a folder on my NAS that another process&#xA;&gt; watches and performs the audio stripping workflow&#xA;&#xA;## Use Case 2&#xA;&#xA;I just wrote about [[if-you-want-something-make-it-so-song-style]] which is the&#xA;second use case - cutting mashups of my favorite songs on youtube and then&#xA;hosting them myself for easy listening&#xA;&#xA;# The Setup&#xA;&#xA;I run it in docker compose like practically all my other services&#xA;&#xA;```yml&#xA;services:&#xA;  pinchflat:&#xA;    container_name: &#34;pinchflat&#34;&#xA;    image: &#34;ghcr.io/kieraneglin/pinchflat:latest&#34;&#xA;    ports:&#xA;      - &#34;8945:8945&#34;&#xA;    volumes:&#xA;      - &#34;/tank/encrypted/docker/the-pit-zfs/pinchflat/config:/config:rw&#34;&#xA;      - &#34;/tank/encrypted/nas/media/downloads/pinchflat/downloads:/downloads:rw&#34;&#xA;    environment:&#xA;      TZ: &#34;America/Chicago&#34;&#xA;      PUID: &#34;1000&#34;&#xA;      PGID: &#34;1000&#34;&#xA;    restart: unless-stopped&#xA;    deploy:&#xA;      resources:&#xA;        limits:&#xA;          memory: &#34;4g&#34;&#xA;```&#xA;&#xA;# The GUI&#xA;&#xA;The WebUI is easy to navigate - you organize your downloads however you want with &#34;sources&#34;, and here&#39;s how I setup the source for these mashups that I want to edit... I add them to my playlist and Pinchflat grabs them for me automatically&#xA;![20250614144201_fa16e7ac.png](https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250614144201_fa16e7ac.png)&#xA;&#xA;![20250614144307_bdf12ee0.png](https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250614144307_bdf12ee0.png)&#xA;&#xA;That&#39;s basically it - then as you can see in the compose file, I get the files in a folder on my NAS and from there I can edit them as I need.&#xA;&#xA;## Example&#xA;&#xA;The church app that does the audio processing is in a compose stack with the&#xA;pinchflat download directory on the host mounted in - this is how containers in&#xA;different stacks can share data, by sharing a filesystem bind mount&#xA;&#xA;```yml&#xA;services:&#xA;  olivet_watcher_app:&#xA;    image: pypeaday/vocal-remover-watcher&#xA;    container_name: olivet-youtube-watcher&#xA;    volumes:&#xA;      - /tank/encrypted/nas/media/downloads/pinchflat/downloads:/input:ro&#xA;      - /tank/encrypted/docker/vocal_remover_app/watcher-app/processed_mp3s:/output&#xA;      - /tank/encrypted/docker/vocal_remover_app/watcher-app/db:/data&#xA;    working_dir: /app&#xA;```&#xA;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>If You Want Something Make It So - Song Style</title>
    <id>https://pype.dev/if-you-want-something-make-it-so-song-style/</id>
    <updated>2025-06-14T08:44:14Z</updated>
    <published>2025-06-14T08:44:14Z</published>
    <link href="https://pype.dev/if-you-want-something-make-it-so-song-style/" rel="alternate" type="text/html"></link>
    <summary type="text">In grad school a professor of mine, Mark Hunacek, said one of the most profound things I&#39;ve ever heard to the tune &#34;if you want it, then make it so&#34;... It&#39;s...</summary>
    <content type="text">&#xA;In grad school a professor of mine, Mark Hunacek, said one of the most profound&#xA;things I&#39;ve ever heard to the tune &#34;if you want it, then make it so&#34;... It&#39;s a&#xA;great benefit to mathematicians at the bar to start a conversation with &#34;hey&#xA;let&#39;s assume X because we can&#34;...&#xA;&#xA;This phrase has affected my work greatly to the work I do and how I go about it- &#xA;it&#39;s literally changed how I design some of my code. But I also want this&#xA;mantra to flow into other parts of my life...&#xA;&#xA;&gt; So here&#39;s a post about how I use Pinchflat and Davinci Resolve to tickle my&#xA;&gt; brain with bespoke versions of beautifully crafted mashups&#xA;&#xA;In this example I took a Goobsie mashup, cut the part I didn&#39;t like quite as&#xA;much (though admittedly it&#39;s still beautiful) and spliced it with itself to&#xA;give me a longer running version of a musical piece that takes me to another&#xA;world...&#xA;&#xA;[OG Youtube Mashup](https://www.youtube.com/watch?v=7v7nreDnmDg)&#xA;&#xA;## Acquiring the Media&#xA;&#xA;Pinchflat isn&#39;t really necessary here, anyone can use `youtubedl` or another&#xA;tool to download from YouTube. I do use Pinchflat to subscribe to Youtube&#xA;playlists to automate this process for me. See more about that in&#xA;[[homelab-pinchflat]]&#xA;&#xA;## Creating the Mashup&#xA;&#xA;So Goobsie makes actually good mashups, and I&#39;m not anything even remotely close to an audio engineer or whatever, but there&#39;s a segment of this song that just strikes my whole body in a unique way and I want to sometimes just listen to it conveniently... So enter Davinci Resolve... Basically I took the downloaded file, added it twice to a timeline, and then faded in and out until it sounded ok to me.&#xA;&#xA;![20250614135418_b75bc26a.png](https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250614135418_b75bc26a.png)&#xA;&#xA;## Listening to the Mashup&#xA;&#xA;So now how do I listen to this?&#xA;&#xA;For the moment, it&#39;s a favorite in my Jellyfin library and I listen through&#xA;that client. It&#39;s a TODO item for me to set-up a more music-centric streaming&#xA;service&#xA;&#xA;&#xA;!!! info &#34;Go Forth&#34;&#xA;    So Go Forth - and if you want something, make it so</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>ZSA typing challenge issue</title>
    <id>https://pype.dev/zsa-typing-challenge-issue/</id>
    <updated>2025-06-13T08:07:41Z</updated>
    <published>2025-06-13T08:07:41Z</published>
    <link href="https://pype.dev/zsa-typing-challenge-issue/" rel="alternate" type="text/html"></link>
    <summary type="text">I love zsa and have been using a moonlander for a few years now.</summary>
    <content type="html">&lt;h1 id=&#34;zsa&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;ZSA&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;I love &lt;a href=&#34;https://zsa.io&#34;&gt;zsa&lt;/a&gt; and have been using a moonlander for a few years now.&lt;/p&gt;&#xA;&lt;p&gt;They recently launched &lt;a href=&#34;https://typ.ing&#34;&gt;typ.ing&lt;/a&gt; as a way to train your typing skills - it&amp;rsquo;s a lot like &lt;a href=&#34;https://monkeytype.com&#34;&gt;monkeytype&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;I have a thought about it &lt;a href=&#34;https://thoughts.waylonwalker.com/post/682&#34;&gt;here&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;today-s-challenge&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Today’s Challenge&lt;/span&gt; &lt;a href=&#34;#today-s-challenge&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I went to do today&amp;rsquo;s daily challenge and have ran into an issue where part of&#xA;the challenge is to type &lt;code&gt;/&lt;/code&gt; the forward slash character but it&amp;rsquo;s actually a&#xA;keybind on the website for navigation (well done btw!)&lt;/p&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250613130724_06b0f9ef.png&#34; alt=&#34;20250613130724_06b0f9ef.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;So when I try to type the challenge I actually bring up the nav menu&lt;/p&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250613131031_ce06cf48.png&#34; alt=&#34;20250613131031_ce06cf48.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;So for today I&amp;rsquo;ll take the error on the character to complete it and maybe ZSA&#xA;can look into this?&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Double Check Your DNS Records</title>
    <id>https://pype.dev/double-check-your-dns-records/</id>
    <updated>2025-06-13T06:53:50Z</updated>
    <published>2025-06-13T06:53:50Z</published>
    <link href="https://pype.dev/double-check-your-dns-records/" rel="alternate" type="text/html"></link>
    <summary type="text">I host my blog on cloudflare and manage my infra with terraform. I got a 522 when I went to recently and I wondered why since worked fine...</summary>
    <content type="html">&lt;h1 id=&#34;my-blog&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;My Blog&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;I host &lt;a href=&#34;https://pype.dev&#34;&gt;my blog&lt;/a&gt; on cloudflare and manage my infra with&#xA;terraform. I got a 522 when I went to &lt;code&gt;https://www.pype.dev&lt;/code&gt; recently and I&#xA;wondered why since &lt;code&gt;https://pype.dev&lt;/code&gt; worked fine&amp;hellip;&lt;/p&gt;&#xA;&lt;h2 id=&#34;terraform&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Terraform&lt;/span&gt; &lt;a href=&#34;#terraform&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I had this right in the terraform:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;resource&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;cloudflare_pages_domain&amp;#34; &amp;#34;cf_domain&amp;#34;&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;  account_id&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;local&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;account_id&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;  project_name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;cloudflare_pages_project&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;build_config&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;name&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;  domain&lt;/span&gt;       &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;pype.dev&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But turns out the &lt;code&gt;www&lt;/code&gt; record was commented out for some reason in my terraform code:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;resource&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;cloudflare_pages_domain&amp;#34; &amp;#34;cf_domain_www&amp;#34;&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;  account_id&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;local&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;account_id&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;  project_name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;cloudflare_pages_project&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;build_config&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;name&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;  domain&lt;/span&gt;       &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;www.pype.dev&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A quick &lt;code&gt;terraform apply -auto-approve&lt;/code&gt; (careful with this) and we&amp;rsquo;re up and&#xA;running with the &lt;code&gt;www&lt;/code&gt; record now&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>💭 “We would be less confidential than Google” – Proton threatens…</title>
    <id>https://pype.dev/thoughts-690/</id>
    <updated>2025-06-13T02:19:29Z</updated>
    <published>2025-06-13T02:19:29Z</published>
    <link href="https://pype.dev/thoughts-690/" rel="alternate" type="text/html"></link>
    <summary type="text">I&#39;ve been a proton user for several years now, and pay a decently hefty subscription fee for some of their services that</summary>
    <content type="text">&#xA;&lt;a href=&#34;https://www.techradar.com/vpn/vpn-privacy-security/we-would-be-less-confidential-than-google-proton-threatens-to-quit-switzerland-over-new-surveillance-law?ref=dailydev&#34;&gt;&#xA;    &lt;img&#xA;        src=&#34;https://shots.wayl.one/shot/?url=https://www.techradar.com/vpn/vpn-privacy-security/we-would-be-less-confidential-than-google-proton-threatens-to-quit-switzerland-over-new-surveillance-law?ref=dailydev&amp;height=450&amp;width=800&amp;scaled_width=800&amp;scaled_height=450&amp;selectors=&#34;&#xA;        alt=&#34;shot of post - &#34;We would be less confidential than Google&#34; – Proton threatens to quit Switzerland over new surveillance law | TechRadar&#34;&#xA;        height=450&#xA;        width=800&#xA;    &gt;&#xA;&lt;/a&gt;&#xA;&#xA;Here&#39;s my thought on &lt;a href=&#34;https://www.techradar.com/vpn/vpn-privacy-security/we-would-be-less-confidential-than-google-proton-threatens-to-quit-switzerland-over-new-surveillance-law?ref=dailydev&#34;&gt;&#34;We would be less confidential than Google&#34; – Proton threatens to quit Switzerland over new surveillance law | TechRadar&lt;/a&gt;&#xA;&#xA;---&#xA;&#xA;I&#39;ve been a proton user for several years now, and pay a decently hefty subscription fee for some of their services that I love having access to (multiple domains, email relay, simplelogin, etc.). This privacy impact in Switzerland is concerning and I am definitely biting my nails over the future of this platform&#xA;&#xA;---&#xA;&#xA;!!! note&#xA;    This is one of [[ my-thoughts ]]. I picked this up from [Waylon Walker](https://waylonwalker.com)(https://thoughts.waylonwalker.com). It&#39;s a short note that I make about someone else&#39;s content online.  Learn more about the process [[ thoughts ]]&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Example For Andrew</title>
    <id>https://pype.dev/example-for-andrew/</id>
    <updated>2025-06-08T14:48:53Z</updated>
    <published>2025-06-08T14:48:53Z</published>
    <link href="https://pype.dev/example-for-andrew/" rel="alternate" type="text/html"></link>
    <content type="html">&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250608194801_809d5306.png&#34; alt=&#34;20250608194801_809d5306.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>I built a simple app for adding images to my blog</title>
    <id>https://pype.dev/i-built-a-simple-app-for-adding-images-to-my-blog/</id>
    <updated>2025-06-07T13:30:28Z</updated>
    <published>2025-06-07T13:30:28Z</published>
    <link href="https://pype.dev/i-built-a-simple-app-for-adding-images-to-my-blog/" rel="alternate" type="text/html"></link>
    <summary type="text">I built a simple fastAPI app called &#34;shotput&#34; that I run locally inside a git repo where I save images for my blog. The app is simple:</summary>
    <content type="text">&#xA;# Quick Deets&#xA;&#xA;I built a simple fastAPI app called &#34;shotput&#34; that I run locally inside a git repo where I save images for my blog. The app is simple:&#xA;&#xA;1. upload image from clipboard&#xA;2. app commits image to repo (path is configurable)&#xA;3. app pushes the commit (auto-push configurable)&#xA;4. app returns a markdown link I can paste in my blog that uses statically.io (see [[statically-io-to-help-me-out]]) to serve the image from the repo to my blog&#xA;&#xA;See the image repo with app details at [images.pype.dev](https://github.com/pypeaday/images.pype.dev)&#xA;&#xA;# Usage&#xA;&#xA;Anyone could copy the script and config to their own git repo to put images in&#xA;and run this at home - instructions are in the readme but for simple running on localhost it&#39;s just `uv run`&#xA;&#xA;# Example&#xA;&#xA;![20250607130609_dadd33eb.png](https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250607130609_dadd33eb.png)&#xA;&#xA;pasting an image let&#39;s you copy the markdown link for easy pasting&#xA;&#xA;```markdown&#xA;![20250607130609_dadd33eb.png](https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250607130609_dadd33eb.png)&#xA;```&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Double check your CIDR blocks!</title>
    <id>https://pype.dev/double-check-your-cidr-blocks/</id>
    <updated>2025-06-07T07:27:31Z</updated>
    <published>2025-06-07T07:27:31Z</published>
    <link href="https://pype.dev/double-check-your-cidr-blocks/" rel="alternate" type="text/html"></link>
    <summary type="text">Copy paste - don&#39;t rely on typing correctly...</summary>
    <content type="html">&lt;h1 id=&#34;tl-dr&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;tl;dr&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;Copy paste - don&amp;rsquo;t rely on typing correctly&amp;hellip;&lt;/p&gt;&#xA;&lt;h1 id=&#34;the-issue&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Issue&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;I use tailscale at home and generally love it. One thing I use it for is&#xA;whitelisting - so I have some apps publically available and my homelab ones&#xA;have DNS with SSL certs by LE but I whitelist to only my private IPs so that I&#xA;can use https at home basically. However I have had a few issues&#xA;with a couple apps, and I kind of chaulked it up to &amp;ldquo;network protocol this&amp;rdquo;&#xA;&amp;ldquo;need to figure out that header that&amp;rdquo; but ultimately I was being lazy and the&#xA;issues weren&amp;rsquo;t catastrophic&amp;hellip; it was things like:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;couldn&amp;rsquo;t get to my NVR by DNS, so I&amp;rsquo;d have to use tailscale_ip:port&lt;/li&gt;&#xA;&lt;li&gt;couldn&amp;rsquo;t login with my user in jellyfin cause I lock me down to LAN only&#xA;since I dont&amp;rsquo; use a password&lt;/li&gt;&#xA;&lt;li&gt;gotify wouldn&amp;rsquo;t connect using DNS&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;These things aren&amp;rsquo;t huge but they are annoying and today I decided to figure it out.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h2 id=&#34;typo&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Typo!&lt;/span&gt; &lt;a href=&#34;#typo&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I&amp;rsquo;m not an expert yet but I think the main problem was the CIDR block I was&#xA;using in my traefik config.&lt;/p&gt;&#xA;&lt;p&gt;This&amp;rsquo;ll shock some of you but &lt;code&gt;10.64.0.0/10&lt;/code&gt; and &lt;code&gt;100.64.0.0/10&lt;/code&gt; are not the&#xA;same blocks!&lt;/p&gt;&#xA;&lt;div class=&#34;admonition warning&#34;&gt;&#xA;&lt;p class=&#34;admonition-title&#34;&gt;Check your CIDRs&lt;/p&gt;&#xA;&lt;p&gt;It&amp;rsquo;s always DNS, and even when it&amp;rsquo;s not, it&amp;rsquo;s still probably networking&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>homelab-journey-part-1</title>
    <id>https://pype.dev/homelab-journey-part-1/</id>
    <updated>2025-06-05T08:19:57Z</updated>
    <published>2025-06-05T08:19:57Z</published>
    <link href="https://pype.dev/homelab-journey-part-1/" rel="alternate" type="text/html"></link>
    <summary type="text">I want to start writing about my homelab and this first post can be a short introduction to how I got into homelabbing and a review of my current hardware....</summary>
    <content type="text">&#xA;# Introduction&#xA;&#xA;I want to start writing about my homelab and this first post can be a short&#xA;introduction to how I got into homelabbing and a review of my current hardware.&#xA;I&#39;ll hopefully write about the evolution of my homelab to get to this&#xA;current point and then start writing about updates as new things hit the lab.&#xA;&#xA;# The Journey&#xA;&#xA;## Applications | Pi-Hole&#xA;&#xA;I started with a pi-hole appliance running on a pi-0 I&#xA;had lying around. So, a little introduction into SSH and foreign operating&#xA;systems (I was loosely familiar with Linux and so Raspbian wasn&#39;t a huge deal&#xA;to start with) and then you could just [install pi-hole](https://docs.pi-hole.net/main/basic-install/).&#xA;After installing it I got to learn a little bit about networking, DNS, DHCP,&#xA;etc. all from just exploring and trying out the features of pi-hole.&#xA;&#xA;## Hardware&#xA;&#xA;From there I happened to come into a few computers kind of for free that a church was&#xA;recycling and so now with new-to-me x86 hardware and armed with a tiny bit of&#xA;docker experience at work - I thought &#34;well I wonder if I could run pi-hole in&#xA;docker on a Linux machine?&#34; and that opened the door to running other things in docker.&#xA;&#xA;# Applications | Free-NAS&#xA;&#xA;I quickly decided I wanted a NAS after talking with a friend at work, and one&#xA;of those computers that I inherited was the perfect target for Freenas by iX&#xA;systems (Freenas has since morphed into a few things - primarily TrueNAS Core&#xA;for the homelabber). That got me somewhat familiar with jails (which is a BSD&#xA;concept as FreeNAS was based on FreeBSD, not Linux) and running&#xA;containers in different ways and then I decided I wanted Linux so I rebuilt with&#xA;Ubuntu.&#xA;&#xA;!!! note &#34;&#34;&#xA;&#xA;    there&#39;s been several hardware changes and such in there but that&#xA;    does more or less get me to arrive at where I&#39;m at today which is I have a&#xA;    few different boxes running pretty standard operating systems for their&#xA;    purposes and they are as follows.&#xA;&#xA;# Current Homelab Setup&#xA;&#xA;!!! note &#34;Find updated information at [[the-homelab]]&#34;&#xA;&#xA;## Ad blocking | Pi-Hole&#xA;&#xA;Hardware: pi-3&#xA;&#xA;I have a Raspberry Pi 3 hardwired in that is running pi-hole so that&#39;s been a&#xA;part of my infrastructure now for a long time.&#xA;&#xA;## Router | OPNSense&#xA;&#xA;!!! note &#34;stats&#34;&#xA;&#xA;    CPU: i5-8700&#xA;&#xA;    Memory: 8GB of whatever was in the box&#xA;&#xA;    Storage: 1TB SSD&#xA;&#xA;My router is an old Optiplex SFF 5060 I got from Amazon for less than $100.&#xA;So I&#39;m running a x86 system for my router with&#xA;OpenSense on it. Just seemed it to be another home lab standard and I&#39;d like to&#xA;someday bring pi-hole over there or use AdGuard or integrate those two things&#xA;maybe a little bit more completely but right now they are mostly separate.&#xA;&#xA;## Networking | VLANs&#xA;&#xA;There&#39;s a&#xA;managed switch in there for some VLAN tomfoolery for my cameras and an IOT&#xA;network type of a thing.&#xA;&#xA;## Networking | VPN | Tailscale&#xA;&#xA;They&#39;re on tailscale as well so my DNS happens over tailscale.&#xA;&#xA;## My Desktop&#xA;&#xA;!!! note &#34;stats&#34;&#xA;&#xA;    CPU: Ryzen 7 5700X&#xA;&#xA;    GPU: Nvidia 3090&#xA;&#xA;    Memory: 64 GB&#xA;&#xA;    Storage: 4TB SSD + 2 TB HDD for zfs backup&#xA;&#xA;    OS: Universal Blue Aurora&#xA;&#xA;My daily-driver desktop is somewhat apart of my homelab now as I have a 3090 in&#xA;there with 20 GB of VRAM so I can run some heavier LLMs for self-hosted AI&#xA;workloads. Everything in that space runs in a container and then I manage&#xA;docker containers with compose stacks and portainer for visibility.&#xA;&#xA;### Applications&#xA;&#xA;Some of the apps I run here are ollama, open-webui, automatic1111&#39;s stable diffusion webui, whisper-webui&#xA;&#xA;## NAS / Server&#xA;&#xA;!!! note &#34;stats&#34;&#xA;&#xA;    CPU: Ryzen 7 5700G&#xA;&#xA;    GPU: None right now&#xA;&#xA;    Memory: 128 GB&#xA;&#xA;    Storage: 2x12 TB ZFS Mirror + another 2x12 TB ZFS Mirror + 500GB disk for NVR&#xA;&#xA;    OS: Ubuntu Server 24.04&#xA;&#xA;At the moment I am managing containers using Docker Compose stacks. Many&#xA;applications have their own stack but then I also have stacks of many&#xA;applications. The Compose files are all organized by host and they&#39;re in git&#xA;and I use GitHub as my main get back and remote storage.&#xA;&#xA;### Applications&#xA;&#xA;There are currently 74 containers running on my server, I will not list them all but here&#39;s some highlights:&#xA;&#xA;- traefik&#xA;- portainer&#xA;- nextcloud&#xA;- jellyfin&#xA;- \*arr stack&#xA;- code-server&#xA;- kanboard&#xA;&#xA;I regularly spin up compose stacks to try new things as I hear about them in&#xA;newsletters and such - I will be making an attempt to write about them more&#xA;frequently in a homelabbing series&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Backups interrupted by full disk usage</title>
    <id>https://pype.dev/backups-interrupted-by-full-disk-usage/</id>
    <updated>2025-06-03T21:08:50Z</updated>
    <published>2025-06-03T21:08:50Z</published>
    <link href="https://pype.dev/backups-interrupted-by-full-disk-usage/" rel="alternate" type="text/html"></link>
    <summary type="text">I just got a message from HCIO that my primary backup script is late... This happens every now and then but I decided to check on it... Quickly in and I...</summary>
    <content type="html">&lt;p&gt;I just got a message from HCIO that my primary backup script is late&amp;hellip; This&#xA;happens every now and then but I decided to check on it&amp;hellip; Quickly &lt;code&gt;ssh&lt;/code&gt; in and&#xA;I notice it takes a long time to connect, but nothing errors out&amp;hellip; I&amp;rsquo;ve been&#xA;in the game long enough to think this kind of latency is often disk IO. After&#xA;waiting a bit and haulting the zshrc sourcing, I hit a &lt;code&gt;sudo dust / -H&lt;/code&gt; and bam&amp;hellip;&#xA;There&amp;rsquo;s a container logfile that&amp;rsquo;s about 80GB sitting in &lt;code&gt;/var&lt;/code&gt;&amp;hellip;&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;  75G   │ │ │ │   ┌── 57409a7f8d3168b368e0230babd08ec2e20aabb288806aa13652db1e653a0eee-json.log&#xA;  75G   │ │ │ │ ┌─┴ 57409a7f8d3168b368e0230babd08ec2e20aabb288806aa13652db1e653a0eee           &#xA;  76G   │ │ │ ├─┴ containers                                                                   &#xA;  83G   │ │ ├─┴ docker                                                                         &#xA;  85G   │ ├─┴ lib                                                                              &#xA;  90G   ├─┴ var                                                                                &#xA; 117G ┌─┴ /&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Easy enough to remove, but I need to setup some alerts on disk usage, and&#xA;identify the container to limit the log file size&lt;/p&gt;&#xA;&lt;div class=&#34;admonition info&#34;&gt;&#xA;&lt;p class=&#34;admonition-title&#34;&gt;Useful Notifications&lt;/p&gt;&#xA;&lt;p&gt;I use healthchecks.io to monitor several scripts. You can self-host it but&#xA;I use the hosted service since he has simple Signal integration&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Windows Update Broke Wifi</title>
    <id>https://pype.dev/windows-update-broke-wifi/</id>
    <updated>2025-06-01T14:30:43Z</updated>
    <published>2025-06-01T14:30:43Z</published>
    <link href="https://pype.dev/windows-update-broke-wifi/" rel="alternate" type="text/html"></link>
    <summary type="text">After an unapproved windows update on a machine I help administer for my church, the wifi became super finnicky. I had installed a pretty standard AX5400...</summary>
    <content type="html">&lt;h1 id=&#34;windows-update-behind-my-back&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Windows Update Behind My Back&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;After an unapproved windows update on a machine I help administer for my church, the wifi&#xA;became super finnicky. I had installed a pretty standard AX5400 WiFi 6 PCIe&#xA;adapter and things were great for a while.&lt;/p&gt;&#xA;&lt;h2 id=&#34;isp-and-top-tier-laziness&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;ISP and Top-Tier Laziness&lt;/span&gt; &lt;a href=&#34;#isp-and-top-tier-laziness&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;The ISP installed the modem and router/AP combo all in one room encased in CMU block in the basement&amp;hellip;&#xA;That is in the worst possible spot in the entire building and the Windows&#xA;computer of note is as far away from it as possible - but we were cooking just fine with that PCIe card.&#xA;Suddenly though, after the update and reboot the machine quit receiving an IPv4&#xA;address via that interface&amp;hellip; Many applications broke in odd ways, and the&#xA;browser connected to some websites but not others.&lt;/p&gt;&#xA;&lt;h2 id=&#34;state-matters&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;State Matters&lt;/span&gt; &lt;a href=&#34;#state-matters&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;It took a lot of troubleshooting because of 2 things in the mix&amp;hellip;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Tailscale&lt;/li&gt;&#xA;&lt;li&gt;A second Wi-Fi adapter via USB dongle that was installed while I was out of town (due to the WiFi issues)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;So because of these 2 things, and mostly the USB adapter I think, we saw odd&#xA;behavior that was inconsistent and hard to explain. After having sorted through a bit, I think the intermittent nature of the problems was due to the USB dongle getting an IPv4 address when the connectivity via the default interface was messed up - I can&amp;rsquo;t claim to know if or how Windows would handle this, but it&amp;rsquo;s the only thing that makes sense to me as to why some of the appliations would work and then randomly fail - it&amp;rsquo;s the USB dongle losing connection&amp;hellip; The extra layer is that the bad NIC (the PCIe card) was getting an IPv6 address so the internet connectivity worked EXCEPT FOR THINGS ON MY TAILNET - for example the Nextcloud instance the church backs some data up to&amp;hellip; So the issues were hard to pin-point.&lt;/p&gt;&#xA;&lt;h2 id=&#34;medium-term-plan&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Medium Term Plan…&lt;/span&gt; &lt;a href=&#34;#medium-term-plan&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Our medium term plan is to move the AP of the church to somewhere more&#xA;convenient after we figure out busting through some concrete walls&amp;hellip;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>homelab-computer-vision-pipelines</title>
    <id>https://pype.dev/homelab-computer-vision-pipelines/</id>
    <updated>2025-05-31T08:18:55Z</updated>
    <published>2025-05-31T08:18:55Z</published>
    <link href="https://pype.dev/homelab-computer-vision-pipelines/" rel="alternate" type="text/html"></link>
    <summary type="text">Done in 11 seconds! Subtitle and audio files are in the outputs folder.</summary>
    <content type="html">&lt;p&gt;Done in 11 seconds! Subtitle and audio files are in the outputs folder.&lt;/p&gt;&#xA;&lt;p&gt;I wanted to talk through an idea I have for some computer vision pipelines at home.&#xA;I heard of a tool called Roboflow, which is like a no-code computer vision pipeline training&#xA;and inference tool.&#xA;It seems very cool.&#xA;I also use Frigate at home, and Frigate supports lots of detection on the NVR side.&#xA;And so deploying a model in Frigate or using Roboflow, depending on what kind of customization&#xA;you would need, you can have these detections potentially be as accurate as you want, at&#xA;least with Roboflow.&#xA;The thing is, I don&amp;rsquo;t know about Frigate, but my ideas are if I have a model at home&#xA;that knows me and my wife and my children by name, then when monitored areas issue detections,&#xA;for example, say I&amp;rsquo;m in the backyard and the temperature is above 80 degrees, have a home&#xA;assistant kick on a sprinkler system or something like that.&#xA;And if my wife is back there and it&amp;rsquo;s 80 degrees, don&amp;rsquo;t do that because she wouldn&amp;rsquo;t want that&#xA;sprinkler on or whatever.&#xA;I think that something like that would be very feasible once you have the model.&#xA;So you would need a way to train the model, which would require gathering data and labeling&#xA;it.&#xA;Then you could train a model in lots of ways, but you need to have the deployment in mind.&#xA;If the deployment was Frigate, you would need to be able to compile that model into some&#xA;TensorFlow Lite thing that can run on a TPU.&#xA;That sounds very possible.&#xA;Otherwise, the Roboflow would probably be the platform for training, and then they make&#xA;the deployment kind of a one-click thing.&#xA;From there, I guess either way, Frigate is running the inference, and so the home assistant&#xA;integration would be about the same.&#xA;Frigate sends notifications over MQTT, and based on the Frigate blueprint that I&amp;rsquo;m using&#xA;for home assistant anyway, based on the object and whatever other conditions you want to&#xA;set in an automation, you do whatever you want to do in home assistant.&#xA;That sounds neat.&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Backups are dope</title>
    <id>https://pype.dev/backups-are-dope/</id>
    <updated>2025-05-27T19:42:27Z</updated>
    <published>2025-05-27T19:42:27Z</published>
    <link href="https://pype.dev/backups-are-dope/" rel="alternate" type="text/html"></link>
    <summary type="text">I accidently chown&#39;d -R an app directory and it totally screwed up the database folder. Luckily I zfs replicate my docker volumes to another drive even on...</summary>
    <content type="text">&#xA;I accidently chown&#39;d -R an app directory and it totally screwed up the database&#xA;folder. Luckily I zfs replicate my docker volumes to another drive even on the&#xA;same host, so a quick [rsync] from /harbor/encrypted/docker/manyfold to&#xA;/tank/encrypted/docker/manyfold got me back up and running since I hadn&#39;t&#xA;replicated the messed up permission set yet&#xA;&#xA;Q: How to link to my rsync like a pro post?&#xA;&#xA;A: Wikilinks `[[rsync-like-a-pro]]` [[rsync-like-a-pro]]&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Aurora U-Blue ZRAM Config</title>
    <id>https://pype.dev/aurora-u-blue-zram-config/</id>
    <updated>2025-05-27T13:51:27Z</updated>
    <published>2025-05-27T13:51:27Z</published>
    <link href="https://pype.dev/aurora-u-blue-zram-config/" rel="alternate" type="text/html"></link>
    <summary type="text">I keep running out of space with my swap getting maxxed out... I don&#39;t know why but U-Blue uses Zram already and apparently I can easily override the defaults:</summary>
    <content type="html">&lt;p&gt;I keep running out of space with my swap getting maxxed out&amp;hellip; I don&amp;rsquo;t know why but U-Blue uses Zram already and apparently I can easily override the defaults:&lt;/p&gt;&#xA;&lt;p&gt;in &lt;code&gt;usr/lib/systemd/zram-generator.conf&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-conf&#34;&gt;&#xA;# This config file enables a /dev/zram0 device with the default settings:&#xA;# — size — same as available RAM or 8GB, whichever is less&#xA;# — compression — most likely lzo-rle&#xA;#&#xA;# To disable, uninstall zram-generator-defaults or create empty&#xA;# /etc/systemd/zram-generator.conf file.&#xA;[zram0]&#xA;zram-size = min(ram, 8192)&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;And so I just made my own file in &lt;code&gt;/etc/systemd/zram-generator.conf&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-conf&#34;&gt;&#xA;[zram0]&#xA;zram-size = min(ram, 16384)&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Pandas.DataFrame info always answers and is sometimes right</title>
    <id>https://pype.dev/pandas-dataframe-info-always-answers-and-is-sometimes-right/</id>
    <updated>2025-05-26T09:08:08Z</updated>
    <published>2025-05-26T09:08:08Z</published>
    <link href="https://pype.dev/pandas-dataframe-info-always-answers-and-is-sometimes-right/" rel="alternate" type="text/html"></link>
    <summary type="text">Today I learned that the of a will always give you an answer, but it is wildly difficult to know how accurate it is, because it depends on the underlying...</summary>
    <content type="html">&lt;h1 id=&#34;til&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;TIL&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;Today I learned that the &lt;code&gt;.info()&lt;/code&gt; of a &lt;code&gt;pandas.DataFrame&lt;/code&gt; will always&#xA;give you an answer, but it is wildly difficult to know how accurate it is, because it depends&#xA;on the underlying data types.&#xA;If everything is a NumPy Dtype, then the result you get is the amount of memory NumPy is using&#xA;under the hood, which is very accurate.&#xA;But as soon as you have something like a Python string in the data frame, now pandas will&#xA;tell you how much memory the NumPy data types are using, and it will give you some quick&#xA;estimate of how much memory space the Python string types are using because numpy is just storing&#xA;a pointer to that data in memory, but this is far less&#xA;accurate because it doesn&amp;rsquo;t actually know what the strings are.&lt;/p&gt;&#xA;&lt;h2 id=&#34;memory-usage-deep-or-true&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Memory Usage Deep or True&lt;/span&gt; &lt;a href=&#34;#memory-usage-deep-or-true&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;To get an honest answer about a DataFrame&amp;rsquo;s memory usage, you need to pass &lt;code&gt;memory_usage=&#39;deep&#39;&lt;/code&gt; to the &lt;code&gt;.info()&lt;/code&gt; method.&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# This is the default&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;In &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;50&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: df.info&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;memory_usage&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;True&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;class &lt;span class=&#34;s1&#34;&gt;&amp;#39;pandas.core.frame.DataFrame&amp;#39;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;RangeIndex: &lt;span class=&#34;m&#34;&gt;10&lt;/span&gt; entries, &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; to &lt;span class=&#34;m&#34;&gt;9&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Data columns &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;total &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt; columns&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &lt;span class=&#34;c1&#34;&gt;#   Column  Non-Null Count  Dtype &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;---  ------  --------------  ----- &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;   s1      &lt;span class=&#34;m&#34;&gt;10&lt;/span&gt; non-null     int64 &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;   s2      &lt;span class=&#34;m&#34;&gt;10&lt;/span&gt; non-null     int64 &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;   s3      &lt;span class=&#34;m&#34;&gt;10&lt;/span&gt; non-null     object&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;dtypes: int64&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;2&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;, object&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;1&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;memory usage: 372.0+ bytes&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Notice that the memory usage has a &lt;code&gt;+&lt;/code&gt; in it? You can force a deeper analysis by passing &lt;code&gt;memory_usage=&#39;deep&#39;&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;In &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;51&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: df.info&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;memory_usage&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;deep&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;class &lt;span class=&#34;s1&#34;&gt;&amp;#39;pandas.core.frame.DataFrame&amp;#39;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;RangeIndex: &lt;span class=&#34;m&#34;&gt;10&lt;/span&gt; entries, &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; to &lt;span class=&#34;m&#34;&gt;9&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Data columns &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;total &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt; columns&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &lt;span class=&#34;c1&#34;&gt;#   Column  Non-Null Count  Dtype &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;---  ------  --------------  ----- &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;   s1      &lt;span class=&#34;m&#34;&gt;10&lt;/span&gt; non-null     int64 &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;   s2      &lt;span class=&#34;m&#34;&gt;10&lt;/span&gt; non-null     int64 &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;   s3      &lt;span class=&#34;m&#34;&gt;10&lt;/span&gt; non-null     object&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;dtypes: int64&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;2&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;, object&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;1&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;memory usage: 792.0 bytes&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>SearXNG</title>
    <id>https://pype.dev/searxng/</id>
    <updated>2025-05-25T08:33:10Z</updated>
    <published>2025-05-25T08:33:10Z</published>
    <link href="https://pype.dev/searxng/" rel="alternate" type="text/html"></link>
    <summary type="text">I heard about SearXNG on a couple podcasts and saw it trending on GitHub several times before I finally decided to stand it up. I used it transparently when...</summary>
    <content type="html">&lt;p&gt;I heard about &lt;a href=&#34;https://searxng.org&#34;&gt;SearXNG&lt;/a&gt; on a couple podcasts and saw it trending on GitHub&#xA;several times before I finally decided to stand it up.&#xA;I used it transparently when trying out &lt;a href=&#34;https://khoj.dev/&#34;&gt;khoj&lt;/a&gt;, a self-hosted AI LLM agent&#xA;playground kind of a thing, but I&amp;rsquo;ve also been messing around with &lt;a href=&#34;https://openwebui.com&#34;&gt;Open-WebUI&lt;/a&gt; to&#xA;have a self-hosted ChatGPT-like experience.&#xA;I don&amp;rsquo;t know if SearchXNG used to be harder to set up, but it was pretty simple with a Docker Compose up&#xA;and a couple configuration options given my personal homelab setup. Using it feels&#xA;very nice.&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;services&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;redis&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;container_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;redis&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;docker.io/valkey/valkey:8-alpine&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;command&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;valkey-server --save 30 1 --loglevel warning&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;restart&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;unless-stopped&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;volumes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;./data/redis:/data&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;logging&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;driver&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;json-file&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;options&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;max-size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;1m&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;max-file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;searxng&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;container_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;searxng&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;docker.io/searxng/searxng:latest&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;restart&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;unless-stopped&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;ports&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;8080:8080&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;volumes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;./data/searxng:/etc/searxng:rw&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;env_file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;.env&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;environment&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# - SEARXNG_BASE_URL=https://${SEARXNG_HOSTNAME:-localhost}/&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;UWSGI_WORKERS=${SEARXNG_UWSGI_WORKERS:-4}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;UWSGI_THREADS=${SEARXNG_UWSGI_THREADS:-4}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;logging&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;driver&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;json-file&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;options&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;max-size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;1m&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;max-file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I love the self-hosted aspect. I love not seeing any ads on my search&#xA;results. I did a few searches where I know what results to expect and&#xA;it did okay.&#xA;It is good right now at filtering out garbage in my results.&lt;/p&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://dropper.wayl.one/api/file/4ff5953c-bc8d-4978-8509-b43582460a0b.png&#34; alt=&#34;SearXNG&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;So I look forward to tweaking it and using it as a search&#xA;backend with open web UI. Next on my list is having enough resources to run&#xA;Ollama and a stable diffusion generator at the same time and have image&#xA;generation working through open web UI.&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>My MCP Configuration</title>
    <id>https://pype.dev/my-mcp-configuration/</id>
    <updated>2025-04-27T05:29:54Z</updated>
    <published>2025-04-27T05:29:54Z</published>
    <link href="https://pype.dev/my-mcp-configuration/" rel="alternate" type="text/html"></link>
    <summary type="text">https://github.com/modelcontextprotocol/servers/tree/main/src/sqlite</summary>
    <content type="html">&lt;h1 id=&#34;my-mcp&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;My MCP&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;h2 id=&#34;the-tools&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Tools&lt;/span&gt; &lt;a href=&#34;#the-tools&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;h3 id=&#34;docker&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Docker&lt;/span&gt; &lt;a href=&#34;#docker&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;h3 id=&#34;ragdocs&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;RAGDocs&lt;/span&gt; &lt;a href=&#34;#ragdocs&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;h3 id=&#34;sequential-thinking&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Sequential Thinking&lt;/span&gt; &lt;a href=&#34;#sequential-thinking&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;h3 id=&#34;git&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Git&lt;/span&gt; &lt;a href=&#34;#git&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;h3 id=&#34;not-tried-yet&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Not Tried Yet&lt;/span&gt; &lt;a href=&#34;#not-tried-yet&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/modelcontextprotocol/servers/tree/main/src/sqlite&#34;&gt;https://github.com/modelcontextprotocol/servers/tree/main/src/sqlite&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-config&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Config&lt;/span&gt; &lt;a href=&#34;#the-config&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;mcpServers&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;docker-mcp&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;#34;command&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;uvx&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;#34;args&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;s2&#34;&gt;&amp;#34;docker-mcp&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;ragdocs&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;command&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;node&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;args&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;/home/nic/projects/personal/quadtask/node_modules/@qpd-v/mcp-server-ragdocs/build/index.js&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;env&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;#34;QDRANT_URL&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;http://babyblue-aurora:6333&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;#34;EMBEDDING_PROVIDER&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;ollama&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;#34;OLLAMA_URL&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;http://babyblue-aurora:11434&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;alwaysAllow&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;search_documentation&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;list_sources&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;test_ollama&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;add_documentation&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;disabled&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;sequentialthinking&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;command&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;docker&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;args&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;run&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;--rm&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;-i&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;--name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;sequentialthinking&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;mcp/sequentialthinking&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;disabled&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;alwaysAllow&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;sequentialthinking&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;git&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;command&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;uvx&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;args&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;mcp-server-git&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;disabled&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;alwaysAllow&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;git_status&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;git_commit&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;git_add&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;git_log&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;git_diff&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>I was wrecked by a weird combo of » and -e</title>
    <id>https://pype.dev/i-was-wrecked-by-a-weird-combo-of-and-e/</id>
    <updated>2025-04-23T08:44:59Z</updated>
    <published>2025-04-23T08:44:59Z</published>
    <link href="https://pype.dev/i-was-wrecked-by-a-weird-combo-of-and-e/" rel="alternate" type="text/html"></link>
    <summary type="text">If state matters then check it in the beginning or handle it on a failure... Let me explain</summary>
    <content type="html">&lt;h2 id=&#34;tl-dr&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;TL;DR&lt;/span&gt; &lt;a href=&#34;#tl-dr&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;If state matters then check it in the beginning or handle it on a failure&amp;hellip; Let me explain&lt;/p&gt;&#xA;&lt;p&gt;I ran into some trouble recently &lt;em&gt;almost&lt;/em&gt; losing some encrypted data&amp;hellip; Now&#xA;this would be the second time I&amp;rsquo;ve had that happen, so I&amp;rsquo;m going to write a&#xA;little bit about it now that I figured it out&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-stage&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Stage&lt;/span&gt; &lt;a href=&#34;#the-stage&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s the scenario - I use &lt;code&gt;ansible-vault&lt;/code&gt; to keep some sensitive data in a&#xA;few public repos, and I keep the keys I use in Bitwarden Secrets Manager.&lt;/p&gt;&#xA;&lt;p&gt;I use &lt;code&gt;just&lt;/code&gt; as a command runner and have common &lt;code&gt;just encrypt&lt;/code&gt; and &lt;code&gt;just decrypt&lt;/code&gt; recipes throughout many justfiles. It might look something like this&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;get-vault-key:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    bws secret get &lt;span class=&#34;nv&#34;&gt;$HOMELAB_BOT_VAULT_KEY_ID&lt;/span&gt;  &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq -r &lt;span class=&#34;s1&#34;&gt;&amp;#39;.value&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;encrypt:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;#!/bin/bash&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; +e&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    just get-vault-key &amp;gt; key&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    ansible-vault encrypt ./secret-file --vault-password-file key&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    ansible-vault encrypt ./secret-file2 --vault-password-file key&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    rm key&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;decrypt:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;#!/bin/bash&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; +e&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    just get-vault-key &amp;gt; key&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    ansible-vault decrypt ./secret-file --vault-password-file key&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    ansible-vault decrypt ./secret-file2 --vault-password-file key&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    rm key&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;spoiler&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Spoiler&lt;/span&gt; &lt;a href=&#34;#spoiler&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Above is a good example of the 2 recipes, but prior to this morning they looked like this&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;get-vault-key:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    bws secret get &lt;span class=&#34;nv&#34;&gt;$HOMELAB_BOT_VAULT_KEY_ID&lt;/span&gt;  &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq -r &lt;span class=&#34;s1&#34;&gt;&amp;#39;.value&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# BAD EXAMPLES! DO NOT DO THIS&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;encrypt:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; -e&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    just get-vault-key &amp;gt;&amp;gt; key&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    ansible-vault encrypt ./secret-file --vault-password-file key&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    ansible-vault encrypt ./secret-file2 --vault-password-file key&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    rm key&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;decrypt:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; -e&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    just get-vault-key &amp;gt;&amp;gt; key&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    ansible-vault decrypt ./secret-file --vault-password-file key&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    ansible-vault decrypt ./secret-file2 --vault-password-file key&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    rm key&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;problem&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Problem&lt;/span&gt; &lt;a href=&#34;#problem&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;So here&amp;rsquo;s the story - in real life I started using distrobox when I ran into&#xA;this and I thought it was an issue with different versions of ansible installed&#xA;in distrobox and on my desktop. After a few more odd deployment workflows I&#xA;think I&amp;rsquo;ve determined that the real problem is that &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt; appends to a file (see&#xA;the issue yet?), but if my recipes fail (say I try to encrypt an already&#xA;encrypted file) then the command exits but what&amp;rsquo;s left on my disk? &lt;code&gt;key&lt;/code&gt; is&#xA;still there&amp;hellip; and the next time I go to run a command I&amp;rsquo;ll echo the real key&#xA;to the &lt;code&gt;key&lt;/code&gt; file again and if I called &lt;code&gt;encrypt&lt;/code&gt; when the first or more files&#xA;in the list were &lt;code&gt;decrypted&lt;/code&gt; then they&amp;rsquo;ll be encrypted not with my key, but&#xA;with my key repeated as many times as I ran a command with &lt;code&gt;just get-vault-key &amp;gt;&amp;gt; key&lt;/code&gt;&#xA;before ever removing the key file!&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nic in pype.dev   main   ×2  ×3  ×7 via   v3.11.10&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;pype-dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; 󰒄 &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ cat secret-file&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Danger, Will Robinson&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nic in pype.dev   main   ×2  ×3  ×7 via   v3.11.10&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;pype-dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; 󰒄 &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ just encrypt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bws secret get &lt;span class=&#34;nv&#34;&gt;$HOMELAB_BOT_VAULT_KEY_ID&lt;/span&gt;  &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq -r &lt;span class=&#34;s1&#34;&gt;&amp;#39;.value&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Encryption successful&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nic in pype.dev   main   ×2  ×3  ×7 via   v3.11.10&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;pype-dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; 󰒄 &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ cat secret-file&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$ANSIBLE_VAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;1.1&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;AES256&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;39616332393662346639633030633766666336323939346138633238626239363733316431333737&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;6463663763366434376437303335643431663431326135300a636261663636336139323033316232&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;37666439383131393631333332353731633661396431633834326432363936613331623135666565&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;6364363039663933620a326563323931643632323031396664646363613636613562366166386439&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;63653661653037393538356461323239396630643338393231306163343964623866&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nic in pype.dev   main   ×2  ×3  ×7 via   v3.11.10&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;pype-dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; 󰒄 &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ just decrypt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bws secret get &lt;span class=&#34;nv&#34;&gt;$HOMELAB_BOT_VAULT_KEY_ID&lt;/span&gt;  &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq -r &lt;span class=&#34;s1&#34;&gt;&amp;#39;.value&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Decryption successful&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nic in pype.dev   main   ×2  ×3  ×7 via   v3.11.10&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;pype-dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; 󰒄 &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ cat secret-file&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Danger, Will Robinson&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So as you can see, I have &lt;code&gt;secret-file&lt;/code&gt; here, and I can encrypt and decrypt&#xA;just fine. But if I have that &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt; in the recipe, add a second file, and a&#xA;failure in a command - well then I&amp;rsquo;ll start getting confused&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;Follow along with the workflow of adding a file that I&amp;rsquo;ll need encrypted&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Only secret-file is in the just recipe here - I add secret-file2 after&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nic in pype.dev   main   ×2  ×3  ×7 via   v3.11.10&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;pype-dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; 󰒄 &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ just decrypt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bws secret get &lt;span class=&#34;nv&#34;&gt;$HOMELAB_BOT_VAULT_KEY_ID&lt;/span&gt;  &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq -r &lt;span class=&#34;s1&#34;&gt;&amp;#39;.value&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ERROR! input is not vault encrypted data. /var/home/nic/projects/personal/pype.dev/secret-file is not a vault encrypted file &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; /var/home/nic/projects/personal/pype.dev/secret-file&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;error: Recipe &lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;decrypt&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt; failed with &lt;span class=&#34;nb&#34;&gt;exit&lt;/span&gt; code &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nic in pype.dev   main   ×2  ×3  ×8 via   v3.11.10&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;pype-dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; 󰒄 &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;✗ &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Good - secret-file is already decrypted! So lets add another file&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Good - secret-file is already decrypted! So lets add another file&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nic in pype.dev   main   ×2  ×3  ×7 via   v3.11.10&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;pype-dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; 󰒄 &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Foo Bar Bam Baz&amp;#34;&lt;/span&gt; &amp;gt; secret-file2                                    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nic in pype.dev   main   ×2  ×3  ×8 via   v3.11.10&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;pype-dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; 󰒄 &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Added secret-file2 to my Just recipes&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Added secret-file2 to my Just recipes&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nic in pype.dev   main   ×2  ×3  ×8 via   v3.11.10&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;pype-dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; 󰒄 &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ just encrypt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bws secret get &lt;span class=&#34;nv&#34;&gt;$HOMELAB_BOT_VAULT_KEY_ID&lt;/span&gt;  &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq -r &lt;span class=&#34;s1&#34;&gt;&amp;#39;.value&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Encryption successful&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Encryption successful&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nic in pype.dev   main   ×2  ×3  ×7 via   v3.11.10&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;pype-dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; 󰒄 &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ just decrypt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bws secret get &lt;span class=&#34;nv&#34;&gt;$HOMELAB_BOT_VAULT_KEY_ID&lt;/span&gt;  &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq -r &lt;span class=&#34;s1&#34;&gt;&amp;#39;.value&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ERROR! Decryption failed &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;no vault secrets were found that could decrypt&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; on /var/home/nic/projects/personal/pype.dev/secret-file &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; /var/home/nic/projects/personal/pype.dev/secret-file&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;error: Recipe &lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;decrypt&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt; failed with &lt;span class=&#34;nb&#34;&gt;exit&lt;/span&gt; code &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nic in pype.dev   main   ×2  ×3  ×8 via   v3.11.10&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;pype-dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; 󰒄 &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;✗ &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Oh no!&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So what happened?&lt;/p&gt;&#xA;&lt;p&gt;Recall that my recipes originally had &lt;code&gt;set -e&lt;/code&gt; at the top and used &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt; to cat&#xA;my secret to a file &lt;code&gt;key&lt;/code&gt;. Well, when the fir| decryption recipe failed the&#xA;&lt;code&gt;key&lt;/code&gt; file was left behind. Then when I went to encrypt both of my files the&#xA;recipe got the key again and made a keyfile like this:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;secretKey&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;secretKey&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The encryption recipe encrypted the files with this key, removed the key file,&#xA;and then the next decryption recipe failed because when it got the key and made&#xA;the file it looked like&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;secretKey&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;So the solution in the end is to remake the &lt;code&gt;key&lt;/code&gt; file every time (&lt;code&gt;&amp;gt;&lt;/code&gt; instead&#xA;of &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;), or check if it exists, or handle the error when the recipe fails, or&#xA;just keep going (&lt;code&gt;set +e&lt;/code&gt;)&lt;/p&gt;&#xA;&lt;h2 id=&#34;fin&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Fin&lt;/span&gt; &lt;a href=&#34;#fin&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;And that&amp;rsquo;s how I lost some secrets in my homelab once, and how I almost lost a&#xA;second time if I hadn&amp;rsquo;t noticed the &lt;code&gt;key&lt;/code&gt; file in my file tree&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Grafana + Gotify for push notifications</title>
    <id>https://pype.dev/grafana-gotify-for-push-notifications/</id>
    <updated>2025-04-07T10:12:51Z</updated>
    <published>2025-04-07T10:12:51Z</published>
    <link href="https://pype.dev/grafana-gotify-for-push-notifications/" rel="alternate" type="text/html"></link>
    <summary type="text">It&#39;s easy to configure push notifications through Gotify from Grafana by setting up a generic Alerting Contact Point...</summary>
    <content type="html">&lt;p&gt;It&amp;rsquo;s easy to configure push notifications through Gotify from Grafana by setting up a generic &lt;code&gt;Webhook&lt;/code&gt; Alerting Contact Point&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;The parameters are:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;HTTP Method: POST&lt;/li&gt;&#xA;&lt;li&gt;URL: http://&lt;gotify url&gt;/message&lt;/li&gt;&#xA;&lt;li&gt;Authentication is done with an app token generated from Gotify, and you put it in &lt;code&gt;Authorization Header: Credentials&lt;/code&gt; in the Grafana configuration&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://dropper.wayl.one/api/file/610b4efb-b4c4-4930-ac63-499d501ba3c3.png&#34;&gt;See image&lt;/a&gt;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>SMB with ZFS on Ubuntu</title>
    <id>https://pype.dev/smb-with-zfs-on-ubuntu/</id>
    <updated>2025-02-20T09:18:35Z</updated>
    <published>2025-02-20T09:18:35Z</published>
    <link href="https://pype.dev/smb-with-zfs-on-ubuntu/" rel="alternate" type="text/html"></link>
    <summary type="text">sudo apt-get install -y samba \\ then set sharesmb=on \\ chown the user \\ smbpasswd -a \\ then mount with user/password from other machine</summary>
    <content type="html">&lt;p&gt;sudo apt-get install -y samba \ then set sharesmb=on \ chown the user \ smbpasswd &lt;user&gt; -a \ then mount with user/password from other machine&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Recovering from zpool corruption when you’re short a drive</title>
    <id>https://pype.dev/recovering-from-zpool-corruption-when-you-re-short-a-drive/</id>
    <updated>2025-02-03T21:08:56Z</updated>
    <published>2025-02-03T21:08:56Z</published>
    <link href="https://pype.dev/recovering-from-zpool-corruption-when-you-re-short-a-drive/" rel="alternate" type="text/html"></link>
    <summary type="text">can only mount tank RO - so can&#39;t rename - also can&#39;t detach which is what I&#39;d want</summary>
    <content type="html">&lt;ol&gt;&#xA;&lt;li&gt;can only mount tank RO&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;so can&amp;rsquo;t rename&lt;/li&gt;&#xA;&lt;li&gt;also can&amp;rsquo;t detach which is what I&amp;rsquo;d want&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;Could import pool witn -N to not mount any datasets&lt;/li&gt;&#xA;&lt;li&gt;detach and attach&lt;/li&gt;&#xA;&lt;li&gt;resilver&amp;hellip;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>The Importance of Nostr According to ChatGPT</title>
    <id>https://pype.dev/the-importance-of-nostr-according-to-chatgpt/</id>
    <updated>2025-01-24T06:38:03Z</updated>
    <published>2025-01-24T06:38:03Z</published>
    <link href="https://pype.dev/the-importance-of-nostr-according-to-chatgpt/" rel="alternate" type="text/html"></link>
    <summary type="text">This was written by ChatGPT with zero oversight from me. There are a few things that are not 100% accurate, but the main idea is there... I am hoping to...</summary>
    <content type="html">&lt;h2 id=&#34;disclaimer&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Disclaimer&lt;/span&gt; &lt;a href=&#34;#disclaimer&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;This was written by ChatGPT with zero oversight from me. There are a few things that are not 100% accurate, but the main idea is there&amp;hellip; I am hoping to actually write about my experience with nostr as I get more involved on the platform.&lt;/p&gt;&#xA;&lt;h3 id=&#34;the-power-of-the-decentralized-social-media-platform-nostr-a-guide-for-beginners&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Power of the Decentralized Social Media Platform Nostr: A Guide for Beginners&lt;/span&gt; &lt;a href=&#34;#the-power-of-the-decentralized-social-media-platform-nostr-a-guide-for-beginners&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;Social media has become a cornerstone of modern communication, allowing individuals to connect across borders and share ideas instantly. However, traditional platforms have raised concerns about censorship, data privacy, and the monopolistic control of user-generated content. &lt;strong&gt;Nostr (Notes and Other Stuff Transmitted by Relays)&lt;/strong&gt;, a decentralized social media protocol, offers a revolutionary alternative by emphasizing freedom, privacy, and user autonomy. This essay explores the transformative power of Nostr, why it matters, and provides a practical guide for beginners to get started.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h3 id=&#34;the-power-of-decentralization-why-nostr-matters&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Power of Decentralization: Why Nostr Matters&lt;/span&gt; &lt;a href=&#34;#the-power-of-decentralization-why-nostr-matters&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;At its core, Nostr is a decentralized protocol designed to enable social media functionality without reliance on centralized servers. Unlike traditional platforms such as Twitter or Facebook, which depend on centralized infrastructure owned by corporations, Nostr operates on a peer-to-peer network facilitated by relays. This structural shift offers several key advantages:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Freedom of Expression&lt;/strong&gt;&lt;br&gt;&#xA;Centralized platforms often act as gatekeepers of content, enforcing moderation policies that can result in censorship. Nostr, on the other hand, allows users to communicate directly without interference from centralized authorities. This makes it particularly valuable for individuals in regions with restrictive speech laws.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Data Ownership&lt;/strong&gt;&lt;br&gt;&#xA;On traditional platforms, users sacrifice ownership of their data, which is often monetized by corporations. Nostr empowers users to retain control over their content and personal information by using cryptographic keys to manage identity.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Resilience Against Shutdowns&lt;/strong&gt;&lt;br&gt;&#xA;Centralized platforms are vulnerable to outages, government intervention, or corporate decisions to deplatform users. Nostr’s decentralized nature ensures that no single entity can shut it down, providing a more resilient communication medium.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Open and Transparent Ecosystem&lt;/strong&gt;&lt;br&gt;&#xA;As an open protocol, Nostr allows developers to create interoperable applications and services. This fosters innovation, enabling users to choose from a variety of client applications while maintaining access to the same network.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;hr&gt;&#xA;&lt;h3 id=&#34;how-nostr-works-the-technical-backbone&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;How Nostr Works: The Technical Backbone&lt;/span&gt; &lt;a href=&#34;#how-nostr-works-the-technical-backbone&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;Nostr uses a simple yet effective system to transmit messages:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Public and Private Keys&lt;/strong&gt;: Each user generates a pair of cryptographic keys. The private key acts as their identity, while the public key serves as their address on the network.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Relays&lt;/strong&gt;: These are lightweight servers that broadcast messages. Users send notes (messages) to relays, which distribute them to other users.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Clients&lt;/strong&gt;: Users access Nostr through client applications, which function as user interfaces. Examples include Damus (for mobile) and Amethyst.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;This decentralized architecture eliminates single points of failure and gives users the flexibility to connect via multiple clients.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h3 id=&#34;a-beginner-s-guide-to-getting-started-with-nostr&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;A Beginner’s Guide to Getting Started with Nostr&lt;/span&gt; &lt;a href=&#34;#a-beginner-s-guide-to-getting-started-with-nostr&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;For those new to Nostr, the decentralized structure might seem intimidating at first. However, with the following step-by-step guide, you’ll be able to join the network and start interacting with others seamlessly.&lt;/p&gt;&#xA;&lt;h4 id=&#34;step-1-generate-your-keys&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Step 1: Generate Your Keys&lt;/span&gt; &lt;a href=&#34;#step-1-generate-your-keys&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h4&gt;&#xA;&lt;p&gt;The first step is to create a pair of cryptographic keys:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Private Key&lt;/strong&gt;: This is your unique identifier and must be kept secret. Treat it like a password.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Public Key&lt;/strong&gt;: This is your &amp;ldquo;address&amp;rdquo; on Nostr and can be shared with others.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Most Nostr client applications automatically generate these keys for you upon sign-up. Ensure you securely back up your private key, as losing it means losing access to your account permanently.&lt;/p&gt;&#xA;&lt;h4 id=&#34;step-2-choose-a-nostr-client&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Step 2: Choose a Nostr Client&lt;/span&gt; &lt;a href=&#34;#step-2-choose-a-nostr-client&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h4&gt;&#xA;&lt;p&gt;Clients are the gateways through which you interact with the Nostr protocol. Popular options include:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Damus&lt;/strong&gt; (iOS/Android): User-friendly and feature-rich.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Amethyst&lt;/strong&gt; (Android): Tailored for Android users with a sleek interface.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Web Clients&lt;/strong&gt;: Platforms like &lt;strong&gt;Nostr.guru&lt;/strong&gt; or &lt;strong&gt;Iris&lt;/strong&gt; allow you to access Nostr via a browser.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Install your chosen client and log in using your keys.&lt;/p&gt;&#xA;&lt;h4 id=&#34;step-3-connect-to-relays&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Step 3: Connect to Relays&lt;/span&gt; &lt;a href=&#34;#step-3-connect-to-relays&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h4&gt;&#xA;&lt;p&gt;Relays are the backbone of the Nostr network, enabling message distribution. Most clients come pre-configured with default relays, but you can add more for better connectivity and reliability. Simply search for &amp;ldquo;Nostr relay services&amp;rdquo; and paste the relay URLs into your client settings.&lt;/p&gt;&#xA;&lt;h4 id=&#34;step-4-explore-and-interact&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Step 4: Explore and Interact&lt;/span&gt; &lt;a href=&#34;#step-4-explore-and-interact&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h4&gt;&#xA;&lt;p&gt;Once set up, you can start exploring the network:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Follow Users&lt;/strong&gt;: Add public keys of other users to your feed.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Post Notes&lt;/strong&gt;: Share your thoughts or updates by creating a note, similar to a tweet.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Engage&lt;/strong&gt;: Interact with others by replying to or liking their notes.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;step-5-customize-your-experience&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Step 5: Customize Your Experience&lt;/span&gt; &lt;a href=&#34;#step-5-customize-your-experience&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h4&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Choose Relays Carefully&lt;/strong&gt;: Some relays may specialize in certain topics or enforce content moderation policies. Tailor your relay list based on your interests and values.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Backup Your Keys&lt;/strong&gt;: Use secure storage solutions like hardware wallets or encrypted cloud storage to protect your private key.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Experiment with Clients&lt;/strong&gt;: Try multiple clients to find the one that suits your preferences.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;hr&gt;&#xA;&lt;h3 id=&#34;the-broader-implications-of-nostr&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Broader Implications of Nostr&lt;/span&gt; &lt;a href=&#34;#the-broader-implications-of-nostr&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;The emergence of platforms like Nostr signals a broader shift toward decentralization in the digital era. By prioritizing user autonomy and privacy, Nostr challenges the centralized paradigms that have dominated the social media landscape for years. Its open architecture invites developers, activists, and everyday users to co-create a more inclusive and censorship-resistant digital space.&lt;/p&gt;&#xA;&lt;p&gt;Moreover, Nostr&amp;rsquo;s impact extends beyond social media. Its decentralized protocol can be adapted for various purposes, such as secure communication, decentralized marketplaces, or even collaborative work environments. This versatility makes it a foundational building block for the next generation of internet technologies.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h3 id=&#34;conclusion&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Conclusion&lt;/span&gt; &lt;a href=&#34;#conclusion&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;Nostr represents a profound evolution in social media, offering a decentralized, user-centric alternative to traditional platforms. By empowering individuals with control over their identity, data, and content, it paves the way for a freer and more resilient online ecosystem. While its decentralized nature may pose a learning curve for beginners, the benefits far outweigh the challenges. By embracing Nostr, we can collectively take a step toward a more open and equitable digital future.&lt;/p&gt;&#xA;&lt;p&gt;For those ready to explore this transformative platform, the journey begins with a simple act: generating your keys and connecting to the network. From there, the power of decentralized communication lies in your hands.&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Deployments are not StatefulSets</title>
    <id>https://pype.dev/deployments-are-not-statefulsets/</id>
    <updated>2025-01-15T18:07:57Z</updated>
    <published>2025-01-15T18:07:57Z</published>
    <link href="https://pype.dev/deployments-are-not-statefulsets/" rel="alternate" type="text/html"></link>
    <summary type="text">I was debugging some ArgoCD stuff earlier today and I love using k9s to explore my k8s resources.</summary>
    <content type="html">&lt;p&gt;I was debugging some ArgoCD stuff earlier today and I love using k9s to explore&#xA;my k8s resources.&lt;/p&gt;&#xA;&lt;p&gt;The TLDR is that I put some bad env vars in the &lt;code&gt;global&lt;/code&gt; values for my ArgoCD&#xA;pods, this caused the webUI to hang. An easy way to push things through is to&#xA;open k9s, view the Deployments, and edit the env vars there so the pods can be&#xA;in the right state to restart and pickup the changes (you&amp;rsquo;ve obviously fixed&#xA;the values file already right?)&lt;/p&gt;&#xA;&lt;p&gt;Well the Notification Controller was the pod hanging, and I couldn&amp;rsquo;t find it in&#xA;the Deployments view! This blew my mind&amp;hellip; until I realized that it was a&#xA;Stateful Set.&lt;/p&gt;&#xA;&lt;p&gt;So, this is not a comparison of the 2 - this is just a note to say that all I&#xA;had to do was find the StatefulSets in k9s and do the same workflow for editing&#xA;what I needed to edit to get the pods into workable state while working on the&#xA;values file&amp;hellip;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>docker context (and an issue to question your sanity)</title>
    <id>https://pype.dev/docker-context-and-an-issue-to-question-your-sanity/</id>
    <updated>2024-12-19T05:59:30Z</updated>
    <published>2024-12-19T05:59:30Z</published>
    <link href="https://pype.dev/docker-context-and-an-issue-to-question-your-sanity/" rel="alternate" type="text/html"></link>
    <summary type="text">docker contexts are great, would recommend putting them in your prompt though (via starship or something else)... here&#39;s why</summary>
    <content type="html">&lt;p&gt;docker contexts are great, would recommend putting them in your prompt though (via starship or something else)&amp;hellip; here&amp;rsquo;s why&lt;/p&gt;&#xA;&lt;p&gt;I like to manage my containers remotely - I have a nice development setup on my desktop and I try to keep my server as bare-bones as possible. For a while I&amp;rsquo;ve been using ansible which makes it easy to manage configuration etc on other machines. But I recently learned about docker contexts and I&amp;rsquo;m planning to scale down my homelab management to just docker-compose stacks rather than a bunch of super complicated ansible playbooks&lt;/p&gt;&#xA;&lt;p&gt;So, setting up a context is easy - it&amp;rsquo;s basically an ssh connection to another machine!&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;docker context create koober --docker &amp;quot;host=ssh://nic@koober&amp;quot;&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;koober&lt;/code&gt; is one of my dev machines and my &lt;code&gt;~/.ssh/config&lt;/code&gt; is setup such that I can &lt;code&gt;ssh nic@koober&lt;/code&gt;, this makes the context work really seamlessly.&lt;/p&gt;&#xA;&lt;p&gt;So there&amp;rsquo;s the &lt;code&gt;default&lt;/code&gt; context (the machine you&amp;rsquo;re on) and now I have &lt;code&gt;koober&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;To use it you run &lt;code&gt;docker context use koober&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;And then to check we can &lt;code&gt;ls&lt;/code&gt; the contexts&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;docker context ls&#xA;NAME       DESCRIPTION                               DOCKER ENDPOINT               ERROR&#xA;default    Current DOCKER_HOST based configuration   unix:///var/run/docker.sock   &#xA;koober *                                             ssh://nic@koober&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Notice the * - that indicates that&amp;rsquo;s our current context.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h2 id=&#34;trouble&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Trouble&lt;/span&gt; &lt;a href=&#34;#trouble&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Now here&amp;rsquo;s where things get hairy&amp;hellip; you&amp;rsquo;ve gotta be super-aware of what context you&amp;rsquo;re using. I have an indicator in my starship prompt that shows the current context, but since I&amp;rsquo;m new to using them I kind of didn&amp;rsquo;t notice it until I ran into this issue&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;m working on a python application in docker but was not able to execute the entrypoint even though I KNEW the file was there&amp;hellip; let&amp;rsquo;s take a look&lt;/p&gt;&#xA;&lt;h3 id=&#34;example&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Example&lt;/span&gt; &lt;a href=&#34;#example&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s a minimal hello world applycation in docker to illustrate the issue&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# main.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;hello world&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;# Use an official Python runtime as a parent image&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;python:3.11-slim&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;# Set the working directory in the container&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;WORKDIR&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;/app&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;# Copy the current directory contents into the container at /app&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;COPY&lt;/span&gt; . /app&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;# Run the main.py script as the container&amp;#39;s main process&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;CMD&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;python&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;main.py&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;services&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;hello-world&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;build&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;volumes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;.:/app&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Notice volume mounting in my project directory &lt;code&gt;.&lt;/code&gt; to &lt;code&gt;/app&lt;/code&gt; as a common practice to develop inside the container&lt;/p&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s where I started to question my sanity&amp;hellip;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;✗ docker compose up                                            &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;+&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; Running 1/0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; ✔ Container docker-context-example-hello-world-1  Created                                                                                                                                                                                                                                                              0.0s &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Attaching to hello-world-1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;hello-world-1  &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; python: can&lt;span class=&#34;s1&#34;&gt;&amp;#39;t open file &amp;#39;&lt;/span&gt;/app/main.py&lt;span class=&#34;err&#34;&gt;&amp;#39;&lt;/span&gt;: &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;Errno 2&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; No such file or directory&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;hello-world-1 exited with code &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;python can&#39;t open file&lt;/code&gt;? hmm&amp;hellip; Let&amp;rsquo;s take a look at the image&lt;/p&gt;&#xA;&lt;p&gt;First let&amp;rsquo;s make sure we get the image name right&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;✗ docker container ls -a              &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;CONTAINER ID   IMAGE                                           COMMAND                  CREATED          STATUS                       PORTS                                                                                  NAMES&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;3d7285fc39e2   docker-context-example-hello-world              &lt;span class=&#34;s2&#34;&gt;&amp;#34;python main.py&amp;#34;&lt;/span&gt;         &lt;span class=&#34;m&#34;&gt;10&lt;/span&gt; minutes ago   Exited &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;2&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;44&lt;/span&gt; seconds ago                                                                                           docker-context-example-hello-world-1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now we can &lt;code&gt;docker run --rm -it --entrypoint /bin/bash --name debug docker-context-example-hello-world&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ docker run --rm -it --entrypoint /bin/bash --name debug docker-context-example-hello-world  &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;root@ee46d0e22de8:/app# python main.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Hello, World!&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;root@ee46d0e22de8:/app# &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;WHAT THE HECK??&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-happened&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;What happened…&lt;/span&gt; &lt;a href=&#34;#what-happened&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;What happened turns out to be pretty simple once we realize I&amp;rsquo;m using contexts&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;koboer&lt;/code&gt; is a remote context, the &lt;code&gt;docker run&lt;/code&gt; and &lt;code&gt;docker compose up&lt;/code&gt; commands are interacting with the docker socket on that machine.&lt;/p&gt;&#xA;&lt;p&gt;So if I compose up the stack notice that there&amp;rsquo;s a volume bind mount in there - well those do &lt;em&gt;not&lt;/em&gt; work with contexts (or at least I&amp;rsquo;m not aware of hose to make it work) and so the &lt;code&gt;/app&lt;/code&gt; directory was getting blown away essentially with an empty overlay&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;But when running with just &lt;code&gt;docker run&lt;/code&gt; with no volume mount, the code was copied in during the build and is right where we expect it&amp;hellip;&lt;/p&gt;&#xA;&lt;h3 id=&#34;let-s-prove-it&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Let’s prove it&lt;/span&gt; &lt;a href=&#34;#let-s-prove-it&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ docker run --rm -it --entrypoint /bin/bash --name debug -v .:/app docker-context-example-hello-world&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;root@903f591c0384:/app# python main.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;python: can&lt;span class=&#34;s1&#34;&gt;&amp;#39;t open file &amp;#39;&lt;/span&gt;/app/main.py&lt;span class=&#34;err&#34;&gt;&amp;#39;&lt;/span&gt;: &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;Errno 2&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; No such file or directory&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;root@903f591c0384:/app# &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;Adding a `-v .:/app` to match the compose file, we get the same error...&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;If we switch to the default context we are back up and running as expected&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;✗ docker context use default&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;default&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Current context is now &lt;span class=&#34;s2&#34;&gt;&amp;#34;default&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nic in /tmp/docker-context-example  via   v3.13.0  &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; 󰒄 󱔎 NO PYTHON ENVIORNMENT SET &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ docker compose up         &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;+&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; Running 1/0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; ✔ Container docker-context-example-hello-world-1  Created                                                                                                                                                                                                                                                              0.0s &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Attaching to hello-world-1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;hello-world-1  &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; Hello, World!&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;hello-world-1 exited with code &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nic in /tmp/docker-context-example  via   v3.13.0  &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; 󰒄 󱔎 NO PYTHON ENVIORNMENT SET &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ docker run --rm -it --entrypoint /bin/bash --name debug -v .:/app docker-context-example-hello-world&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;root@4045b6aa8883:/app# python main.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Hello, World!&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;root@4045b6aa8883:/app# &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Successful runs on both accounts with the volume mount&lt;/p&gt;&#xA;&lt;h2 id=&#34;tldr&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;TLDR&lt;/span&gt; &lt;a href=&#34;#tldr&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Context is king&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Add a healthcheck to your FastAPI app</title>
    <id>https://pype.dev/add-a-healthcheck-to-your-fastapi-app/</id>
    <updated>2024-12-15T15:41:36Z</updated>
    <published>2024-12-15T15:41:36Z</published>
    <link href="https://pype.dev/add-a-healthcheck-to-your-fastapi-app/" rel="alternate" type="text/html"></link>
    <summary type="text">I&#39;m building a few FastAPI apps to throw in docker and run on my homelab... I wanted to add healthchecks and here&#39;s a simple way to do it</summary>
    <content type="html">&lt;p&gt;I&amp;rsquo;m building a few FastAPI apps to throw in docker and run on my homelab&amp;hellip; I wanted to add healthchecks and here&amp;rsquo;s a simple way to do it&lt;/p&gt;&#xA;&lt;p&gt;Make sure to install &lt;code&gt;curl&lt;/code&gt; in the dockerfile (near the top for effeciency)&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;# Install curl with minimal dependencies&#xA;RUN apt-get update &amp;amp;&amp;amp; \&#xA;    apt-get install -y --no-install-recommends curl &amp;amp;&amp;amp; \&#xA;    apt-get clean &amp;amp;&amp;amp; \&#xA;    rm -rf /var/lib/apt/lists/*&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Then I recommend making compose files even for single image deployments&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;services:&#xA;  app:&#xA;    build: .&#xA;    volumes:&#xA;      - type: bind&#xA;        source: .&#xA;        target: /app&#xA;    environment:&#xA;      - PYTHONPATH=/app&#xA;      - DOCKER_ENV=true&#xA;      - UV_VIRTUALENV=/opt/app-env&#xA;    user: &amp;quot;1000:1000&amp;quot;&#xA;    restart: unless-stopped&#xA;    healthcheck:&#xA;      test: [&amp;quot;CMD&amp;quot;, &amp;quot;curl&amp;quot;, &amp;quot;-f&amp;quot;, &amp;quot;http://localhost:8000/health&amp;quot;]&#xA;      interval: 30s&#xA;      timeout: 10s&#xA;      retries: 3&#xA;      start_period: 10s&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Then finally you&amp;rsquo;ll need a &lt;code&gt;/health&lt;/code&gt; endpoint&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@app.get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/health&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;response_class&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;HTMLResponse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;async&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;health_check&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    A health check endpoint that returns a status message.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Service is healthy&amp;lt;/h1&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>statically.io to help me out</title>
    <id>https://pype.dev/statically-io-to-help-me-out/</id>
    <updated>2024-12-14T13:35:31Z</updated>
    <published>2024-12-14T13:35:31Z</published>
    <link href="https://pype.dev/statically-io-to-help-me-out/" rel="alternate" type="text/html"></link>
    <summary type="text">statically.io offers a CDN that I&#39;m going to try to lean into for images in my blog. My hope is that the builds get and stay fast, and that page loads are...</summary>
    <content type="html">&lt;p&gt;&lt;a href=&#34;https://statically.io&#34;&gt;statically.io&lt;/a&gt; offers a CDN that I&amp;rsquo;m going to try to lean into for images in my blog. My hope is that the builds get and stay fast, and that page loads are fast too.&lt;/p&gt;&#xA;&lt;p&gt;Example:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;img&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;src&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/skimpy-zsh.png&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;alt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Skimpy ZSH&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;A fancy data summary in the shell&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;/&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/skimpy-zsh.png&#34; alt=&#34;Skimpy ZSH&#34; title=&#34;A fancy data summary in the shell&#34; /&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>D and uninterruptable sleep</title>
    <id>https://pype.dev/d-and-uninterruptable-sleep/</id>
    <updated>2024-12-11T10:48:10Z</updated>
    <published>2024-12-11T10:48:10Z</published>
    <link href="https://pype.dev/d-and-uninterruptable-sleep/" rel="alternate" type="text/html"></link>
    <summary type="text">I recently have been having significant home server issues, and that&#39;s not the point of this - today I learned what state is when looking at htop.</summary>
    <content type="html">&lt;h2 id=&#34;htop&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Htop&lt;/span&gt; &lt;a href=&#34;#htop&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I recently have been having significant home server issues, and that&amp;rsquo;s not the point of this - today I learned what &lt;code&gt;D&lt;/code&gt; state is when looking at htop.&lt;/p&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/d-htop.png&#34; alt=&#34;htop-d&#34; title=&#34;htop with D state&#34; /&gt;&#xA;&lt;p&gt;Apparently this means &amp;ldquo;uninterruptable sleep&amp;rdquo; and it&amp;rsquo;s a dev&amp;rsquo;s nightmare&amp;hellip;&lt;/p&gt;&#xA;&lt;h3 id=&#34;context&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Context&lt;/span&gt; &lt;a href=&#34;#context&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;The issue I was having was that some &lt;code&gt;zfs rollback&lt;/code&gt; commands were hung - for hours&amp;hellip; I wasn&amp;rsquo;t sure what was going on, rollbacks should be instant but I figured it was just an artifact of these issues.&lt;/p&gt;&#xA;&lt;p&gt;Turns out I still don&amp;rsquo;t know what locked the disks up but I learned why &lt;code&gt;&amp;lt;C&amp;gt;-c&lt;/code&gt; did &lt;strong&gt;nothing&lt;/strong&gt;&amp;hellip;&#xA;the more you know&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Stylus for custom webpage themes</title>
    <id>https://pype.dev/stylus-for-custom-webpage-themes/</id>
    <updated>2024-11-27T06:07:39Z</updated>
    <published>2024-11-27T06:07:39Z</published>
    <link href="https://pype.dev/stylus-for-custom-webpage-themes/" rel="alternate" type="text/html"></link>
    <summary type="text">the Logos web app is DISGUSTINGY bright/white - enough to actually ruin your morning...</summary>
    <content type="html">&lt;p&gt;the Logos web app is DISGUSTINGY bright/white - enough to actually ruin your morning&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;Thankfully there&amp;rsquo;s an extension called &lt;a href=&#34;https://addons.mozilla.org/en-US/firefox/addon/styl-us/&#34;&gt;stylus&lt;/a&gt; and some kind folks in the Logos community created a nice dark theme &lt;a href=&#34;https://userstyles.world/style/18547/logos-web-app-dark-mode&#34;&gt;here&lt;/a&gt;. You simply install the extension, then go to the userstyles link &amp;lt;&amp;ndash; and click &lt;code&gt;install&lt;/code&gt;. It only changes themes for the sites configured - in this case &lt;a href=&#34;app.logos.com&#34;&gt;app.logos.com&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h1 id=&#34;todo-image&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;TODO: image&lt;/span&gt;&lt;/h1&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>DNS Broke After Reboot - Ubuntu 22.04</title>
    <id>https://pype.dev/dns-broke-after-reboot-ubuntu-22-04/</id>
    <updated>2024-11-22T08:08:40Z</updated>
    <published>2024-11-22T08:08:40Z</published>
    <link href="https://pype.dev/dns-broke-after-reboot-ubuntu-22-04/" rel="alternate" type="text/html"></link>
    <summary type="text">I rebooted by server and DNS broke randomly. I have no idea if it was from a kernel update or what but that&#39;s the issue with Ubuntu I guess...</summary>
    <content type="html">&lt;p&gt;I rebooted by server and DNS broke randomly. I have no idea if it was from a kernel update or what but that&amp;rsquo;s the issue with Ubuntu I guess&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;After much toil and none of the other options working for me (sorry to not have those documented here) this is what got me the vic from this &lt;a href=&#34;https://askubuntu.com/questions/1406827/how-to-set-dns-on-ubuntu-22-04-when-you-have-no-netplan-config&#34;&gt;SO Post&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;sudo mkdir /etc/systemd/resolved.conf.d/&#xA;sudo $EDITOR /etc/systemd/resolved.conf.d/dns_servers.conf&lt;/p&gt;&#xA;&lt;p&gt;Most folks probably are good with google (8.8.8.8) and cloudflare (1.1.1.1)&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;[Resolve]&#xA;DNS=8.8.8.8 1.1.1.1&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;But I decided to use tailscale&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;[Resolve]&#xA;DNS=100.100.100.100&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Then restart systemd-resolved&lt;/p&gt;&#xA;&lt;p&gt;sudo systemctl restart systemd-resolved&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>OPNSense Bootstrap Recovery</title>
    <id>https://pype.dev/opnsense-bootstrap-recovery/</id>
    <updated>2024-11-07T08:40:19Z</updated>
    <published>2024-11-07T08:40:19Z</published>
    <link href="https://pype.dev/opnsense-bootstrap-recovery/" rel="alternate" type="text/html"></link>
    <summary type="text">enabling DHCP WAN port ()- running the bootstrap script -</summary>
    <content type="html">&lt;p&gt;enabling DHCP WAN port (&lt;code&gt;dhclient &amp;lt;iface&amp;gt;&lt;/code&gt;)- running the bootstrap script - &lt;code&gt;sh /usr/local/sbin/opnsense-bootstrap&lt;/code&gt;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>docker-remote-add</title>
    <id>https://pype.dev/docker-remote-add/</id>
    <updated>2024-09-17T06:19:00Z</updated>
    <published>2024-09-17T06:19:00Z</published>
    <link href="https://pype.dev/docker-remote-add/" rel="alternate" type="text/html"></link>
    <summary type="text">Add from url??</summary>
    <content type="html">&lt;p&gt;Add from url??&lt;/p&gt;&#xA;&lt;p&gt;ADD &lt;a href=&#34;http://example.com/cars.csv&#34;&gt;http://example.com/cars.csv&lt;/a&gt; /tmp/cars.csv&lt;/p&gt;&#xA;&lt;p&gt;Unpack automatically!? (.tar, .tar.gz, .tgz, .bz2, .tbz2, .txz, .zip)&lt;/p&gt;&#xA;&lt;p&gt;ADD myapp.tar.gz /opt/myapp/&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Docker copy and chown</title>
    <id>https://pype.dev/docker-copy-and-chown/</id>
    <updated>2024-09-17T06:18:09Z</updated>
    <published>2024-09-17T06:18:09Z</published>
    <link href="https://pype.dev/docker-copy-and-chown/" rel="alternate" type="text/html"></link>
    <summary type="text">COPY --chown=myuser:mygroup source-file target-file</summary>
    <content type="html">&lt;p&gt;COPY &amp;ndash;chown=myuser:mygroup source-file target-file&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Switching from AltaCV to RenderCV for my Resume</title>
    <id>https://pype.dev/switching-from-altacv-to-rendercv-for-my-resume/</id>
    <updated>2024-08-01T05:59:46Z</updated>
    <published>2024-08-01T05:59:46Z</published>
    <link href="https://pype.dev/switching-from-altacv-to-rendercv-for-my-resume/" rel="alternate" type="text/html"></link>
    <summary type="text">I was using a fun LaTex-based project for managing my resume called AltaCV. I loved the customization and was familiar with Tek from school. However, I...</summary>
    <content type="html">&lt;p&gt;I was using a fun LaTex-based project for managing my resume called &lt;a href=&#34;https://github.com/liantze/AltaCV&#34;&gt;AltaCV&lt;/a&gt;. I loved the customization and was familiar with Tek from school. However, I update my resume so infrequently that anytime I&amp;rsquo;d hop back to it I&amp;rsquo;d have to remember how to work with Tex and that was frustrating as I&amp;rsquo;ve lost touch with it over the years.&lt;/p&gt;&#xA;&lt;p&gt;Scrolling GitHub treding repos I saw &lt;a href=&#34;https://github.com/sinaatalay/rendercv&#34;&gt;RenderCV&lt;/a&gt; which let&amp;rsquo;s me just use YAML to write my resume and then it compiles to Tek through Python. There&amp;rsquo;s a sister project to make your own using this very easly call &lt;a href=&#34;https://github.com/sinaatalay/rendercv-pipeline&#34;&gt;rendercv-pipeline&lt;/a&gt;. I forked that repo and translated my tek resume to the YAML. The included theme is nice enough is YAML is much easier to maintain long-term.&lt;/p&gt;&#xA;&lt;p&gt;My resume is behind a private GH repo but the example from rendercv-pipeline is &lt;a href=&#34;https://github.com/sinaatalay/rendercv-pipeline/blob/main/John_Doe_CV.pdf&#34;&gt;here on GitHub&lt;/a&gt;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Interesting IPs between Jellyfin clients and server depending on tailscale and server address</title>
    <id>https://pype.dev/interesting-ips-between-jellyfin-clients-and-server-depending-on-tailscale-and-server-address/</id>
    <updated>2024-07-12T06:24:57Z</updated>
    <published>2024-07-12T06:24:57Z</published>
    <link href="https://pype.dev/interesting-ips-between-jellyfin-clients-and-server-depending-on-tailscale-and-server-address/" rel="alternate" type="text/html"></link>
    <summary type="text">When connecting from my phone to jellyfin I&#39;m seeing some interesting patterns.</summary>
    <content type="html">&lt;p&gt;When connecting from my phone to jellyfin I&amp;rsquo;m seeing some interesting patterns.&lt;/p&gt;&#xA;&lt;h2 id=&#34;scenarios&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Scenarios&lt;/span&gt; &lt;a href=&#34;#scenarios&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;h3 id=&#34;tailscale-ip-of-phone-is-listed-as-local-network-to-jellyfin&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Tailscale IP of phone is listed as local network to jellyfin&lt;/span&gt; &lt;a href=&#34;#tailscale-ip-of-phone-is-listed-as-local-network-to-jellyfin&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;Wifi: off&#xA;Tailscale: on&#xA;Use exit node: on&#xA;LAN access: on&#xA;Jellyfin: LAN IP&lt;/p&gt;&#xA;&lt;p&gt;Jellyfin sees 192.168.1.1, my router address&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;p&gt;Wifi: off&#xA;tailscale: on&#xA;Use exit node: on&#xA;LAN access: on&#xA;Jellyfin: Tailscale magic DNS&lt;/p&gt;&#xA;&lt;p&gt;Jellyfin sees the docker bridge network&lt;/p&gt;&#xA;&lt;p&gt;Q: This might be because of traefik somehow&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;p&gt;Wifi: off&#xA;tailsacale: on&#xA;Use exit node: on&#xA;LAN access: off&#xA;Jellyfin: LAN IP&lt;/p&gt;&#xA;&lt;p&gt;Jellyfin sees the 192.168.1.1&lt;/p&gt;&#xA;&lt;p&gt;Q: Why did this work even work?&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;p&gt;Wifi: off&#xA;tailsacale: on&#xA;Use exit node: on&#xA;LAN access: off&#xA;Jellyfin: Tailscale magic DNS&lt;/p&gt;&#xA;&lt;p&gt;Jellyfin sees the docker bridge network&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;p&gt;Wifi: off&#xA;tailsacale: on&#xA;Use exit node: off&#xA;LAN access: off&#xA;Jellyfin: LAN IP&lt;/p&gt;&#xA;&lt;p&gt;Jellyfin sees the 192.168.1.1&lt;/p&gt;&#xA;&lt;p&gt;Q: Why did this work?&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;p&gt;Wifi: off&#xA;tailsacale: on&#xA;Use exit node: off&#xA;LAN access: off&#xA;Jellyfin: Tailscale magic DNS&lt;/p&gt;&#xA;&lt;p&gt;Jellyfin sees the docker bridge network&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;p&gt;Wifi: on&#xA;tailsacale: of&#xA;Use exit node: off&#xA;LAN access: off&#xA;Jellyfin: LAN IP (via pihole DNS)&lt;/p&gt;&#xA;&lt;p&gt;Jellyfin sees the IP of my phone&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Upgrading your kernel can F you up… whoops</title>
    <id>https://pype.dev/upgrading-your-kernel-can-f-you-up-whoops/</id>
    <updated>2024-06-26T10:21:59Z</updated>
    <published>2024-06-26T10:21:59Z</published>
    <link href="https://pype.dev/upgrading-your-kernel-can-f-you-up-whoops/" rel="alternate" type="text/html"></link>
    <summary type="text">https://forum.proxmox.com/threads/update-error-with-coral-tpu-drivers.136888/#post-608975 I lost TPU for frigate, this saved me ass</summary>
    <content type="html">&lt;p&gt;&lt;a href=&#34;https://forum.proxmox.com/threads/update-error-with-coral-tpu-drivers.136888/#post-608975&#34;&gt;https://forum.proxmox.com/threads/update-error-with-coral-tpu-drivers.136888/#post-608975&lt;/a&gt; I lost TPU for frigate, this saved me ass&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Customize K9s</title>
    <id>https://pype.dev/customize-k9s/</id>
    <updated>2024-05-06T11:57:07Z</updated>
    <published>2024-05-06T11:57:07Z</published>
    <link href="https://pype.dev/customize-k9s/" rel="alternate" type="text/html"></link>
    <summary type="text">To customize k9s use the skins from catppuccin or the ones k9s supplies</summary>
    <content type="html">&lt;p&gt;To customize k9s use the skins from catppuccin or the ones k9s supplies&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;OUT&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;XDG_CONFIG_HOME&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;:-&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$HOME&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;/.config&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/k9s/skins&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;mkdir -p &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$OUT&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;curl -L https://github.com/catppuccin/k9s/archive/main.tar.gz &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; tar xz -C &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$OUT&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; --strip-components&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2&lt;/span&gt; k9s-main/dist&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then edit your k9s config&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;# ~/.config/k9s/config.yml&#xA;k9s:&#xA;  ui:&#xA;    skin: catppuccin-mocha&#xA;    # ...or another flavor:&#xA;    # skin: catppuccin-macchiato&#xA;    # skin: catppuccin-frappe&#xA;    # skin: catppuccin-latte&#xA;&#xA;    # ...or the transparent variants:&#xA;    # skin: catppuccin-mocha-transparent&#xA;    # skin: catppuccin-macchiato-transparent&#xA;    # skin: catppuccin-frappe-transparent&#xA;    # skin: catppuccin-latte-transparent&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Other k9s skins are available &lt;a href=&#34;https://github.com/derailed/k9s/tree/master/skins&#34;&gt;here&lt;/a&gt;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Kanboard to keep me focused on my own ideas</title>
    <id>https://pype.dev/kanboard-to-keep-me-focused-on-my-own-ideas/</id>
    <updated>2024-04-20T18:27:07Z</updated>
    <published>2024-04-20T18:27:07Z</published>
    <link href="https://pype.dev/kanboard-to-keep-me-focused-on-my-own-ideas/" rel="alternate" type="text/html"></link>
    <summary type="text">I&#39;ve been using kanboard as a self-hosted kanban board. It&#39;s keeping me focused on Digital Harbor when I&#39;d rather be doing something less productive.</summary>
    <content type="html">&lt;h2 id=&#34;tl-dr&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;TL;DR&lt;/span&gt; &lt;a href=&#34;#tl-dr&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve been using kanboard as a self-hosted kanban board. It&amp;rsquo;s keeping me focused on &lt;a href=&#34;https://myditialharbor.com&#34;&gt;Digital Harbor&lt;/a&gt; when I&amp;rsquo;d rather be doing something less productive.&lt;/p&gt;&#xA;&lt;h2 id=&#34;my-todos&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;My TODOs&lt;/span&gt; &lt;a href=&#34;#my-todos&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s the thing about my TODOs&amp;hellip; they&amp;rsquo;re everywhere. I&amp;rsquo;ve tried a crazy amount of different organizational tactics for my todo items. I&amp;rsquo;ve tried post-it notes, a journal, &lt;code&gt;TODO.md&lt;/code&gt; in specific repos, a master &lt;code&gt;todo&lt;/code&gt; repo, todo CLIs, etc&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;The problem for me was consistency&amp;hellip; I would regularly forget what I was using for TODOs at that moment in my life&amp;hellip; was there a todo file in this project? Do I have a todo repo cloned on this computer? Is this stuff in my journal or on post-it notes?&lt;/p&gt;&#xA;&lt;p&gt;And what do I do with new ideas? Do I organize them centrally or use a repo for the idea I have?&lt;/p&gt;&#xA;&lt;p&gt;It was getting out of hand to a debilitating degree&amp;hellip; For a while I just gave up on being organized at all&amp;hellip; Things would get done as necessary and if I got some motivation to work on something it was immediately smothered with the anxiety of how I was going to organize my work&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;At some point it became too much&amp;hellip; Now, I have some experience with Azure DevOps/Jira for project management and then I came across Kanboard&amp;hellip;&lt;/p&gt;&#xA;&lt;h2 id=&#34;kanboard&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Kanboard&lt;/span&gt; &lt;a href=&#34;#kanboard&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://kanboard.org/&#34;&gt;Kanboard&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;Kanboard is just a self-hosted kanban style todo app. I know there&amp;rsquo;s a ton of these so the TL;DR of my lesson is I picked an app that I would just use based on simplicity of managing and hosting.&lt;/p&gt;&#xA;&lt;p&gt;I have had kanboard running in my homelab for a long time, but I only barely use it intermittenly. And at that rate I didn&amp;rsquo;t spend any real time organizing my tickets, so I wasn&amp;rsquo;t akshuallly using it - it was just a post-it note replacement.&lt;/p&gt;&#xA;&lt;p&gt;But then I had an idea for a genuine business idea, and if I was going to ever have a hope of making it a reality, I needed to stay organized. This was when I decided to give kanboard a little more effort&amp;hellip; I knew I could always remember that I&amp;rsquo;d chosen an app as my TODO solution (given all the time I spent questioning what I was using at any given point in time). I also knew I could host kanboard so that I could get to it from wherever was necessary because my homelab is relatively easy to add another public service to.&lt;/p&gt;&#xA;&lt;p&gt;So once I just decided to lean into this thing, I would take advantage of any moments of motivation and just jot down ideas for things that had to get done&amp;hellip; Simple stuff like explore an infra management option, add one feature to a config, or migrate one website to another stack&amp;hellip; And I would just write these things downs until I have enough time free to crack down on a task. The beautiful thing is, when I am struck with just enough time to do something, and the motivation to do something, I don&amp;rsquo;t waste any time deciding what to do - past-me did present-me a favor and decided what was important already&amp;hellip; So as long as I do myself the favor, when I&amp;rsquo;m ready to go I am never beaten by the anxiety of not knowing what I ant to do or how I&amp;rsquo;ll track what I&amp;rsquo;m doing&amp;hellip; I chose kanboard and even though it&amp;rsquo;s not as fast as a terminal TUI,  it is reliable, simple, and keeps me focused on what I need to do.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-biggest-benefit&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The biggest benefit&lt;/span&gt; &lt;a href=&#34;#the-biggest-benefit&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Not only is just having one app as the solution nice because it&amp;rsquo;s centrally managed and accessible from wherever I need to get it, but the TOP feature of kanboard I use is comments on tickets&amp;hellip; I get to continue to do future-me favors, my jotting down where I&amp;rsquo;m at in a task, what&amp;rsquo;s left to do, what I&amp;rsquo;m trying, etc&amp;hellip; and future-me is in a great mood, because when I have that free few minutes, I can just read my own past thoughts and get back up to speed without wasting time trying to remember things I never would&amp;rsquo;ve remembered if I hadn&amp;rsquo;t written them down!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>DHCP Restart to Save Ubuntu 22.04 Server Networking</title>
    <id>https://pype.dev/dhcp-restart-to-save-ubuntu-22-04-server-networking/</id>
    <updated>2023-12-31T20:26:50Z</updated>
    <published>2023-12-31T20:26:50Z</published>
    <link href="https://pype.dev/dhcp-restart-to-save-ubuntu-22-04-server-networking/" rel="alternate" type="text/html"></link>
    <summary type="text">I moved a computer to a remote location for an off-site backup but when it was powered on it wouldn&#39;t show up on any networks. A solution that got me back in...</summary>
    <content type="html">&lt;p&gt;I moved a computer to a remote location for an off-site backup but when it was powered on it wouldn&amp;rsquo;t show up on any networks. A solution that got me back in was a friend restarting the dhcp client for me:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo dhclient -r -v &amp;lt;interface&amp;gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo dhclient -v &amp;lt;interface&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Simple Port Forwarding OPNSense</title>
    <id>https://pype.dev/simple-port-forwarding-opnsense/</id>
    <updated>2023-10-17T10:26:34Z</updated>
    <published>2023-10-17T10:26:34Z</published>
    <link href="https://pype.dev/simple-port-forwarding-opnsense/" rel="alternate" type="text/html"></link>
    <summary type="text">https://forum.opnsense.org/index.php?topic=8783.0</summary>
    <content type="html">&lt;p&gt;&lt;a href=&#34;https://forum.opnsense.org/index.php?topic=8783.0&#34;&gt;https://forum.opnsense.org/index.php?topic=8783.0&lt;/a&gt;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Refresh Nextcloud Groupfolders after messing around on the filesystem</title>
    <id>https://pype.dev/refresh-nextcloud-groupfolders-after-messing-around-on-the-filesystem/</id>
    <updated>2023-09-23T12:45:06Z</updated>
    <published>2023-09-23T12:45:06Z</published>
    <link href="https://pype.dev/refresh-nextcloud-groupfolders-after-messing-around-on-the-filesystem/" rel="alternate" type="text/html"></link>
    <summary type="text">Exec in as www-data and run ./occ groupfolders:scan folder_id -v (the -v to see what it&#39;s doing)</summary>
    <content type="html">&lt;p&gt;Exec in as www-data and run ./occ groupfolders:scan folder_id -v (the -v to see what it&amp;rsquo;s doing)&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>lsof to find what’s using your filesystem</title>
    <id>https://pype.dev/lsof-to-find-what-s-using-your-filesystem/</id>
    <updated>2023-04-09T13:32:38Z</updated>
    <published>2023-04-09T13:32:38Z</published>
    <link href="https://pype.dev/lsof-to-find-what-s-using-your-filesystem/" rel="alternate" type="text/html"></link>
    <summary type="text">lsof | grep /tank/nas shows me what is using my nas at any time!</summary>
    <content type="html">&lt;p&gt;lsof | grep /tank/nas shows me what is using my nas at any time!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Changing ZFS key for child datasets of encrypted dataset after migration</title>
    <id>https://pype.dev/changing-zfs-key-for-child-datasets-of-encrypted-dataset-after-migration/</id>
    <updated>2023-04-08T20:12:22Z</updated>
    <published>2023-04-08T20:12:22Z</published>
    <link href="https://pype.dev/changing-zfs-key-for-child-datasets-of-encrypted-dataset-after-migration/" rel="alternate" type="text/html"></link>
    <summary type="text">➜ pihole sudo zfs load-key -L file:///path/to/.zfs.tank.key tank/encrypted/vms/arch-sandbox ➜ pihole sudo zfs change-key -o...</summary>
    <content type="html">&lt;p&gt;➜ pihole sudo zfs load-key -L file:///path/to/.zfs.tank.key tank/encrypted/vms/arch-sandbox&#xA;➜ pihole sudo zfs change-key -o keylocation=file:///path/to/.zfs.tank.key -o keyformat=raw tank/encrypted/vms/arch-sandbox&#xA;Need to load-key for each individual dataset, then change key location to be a file instead of the prompt&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Convert Word Doc to PDF with Headless Libreoffice</title>
    <id>https://pype.dev/convert-word-doc-to-pdf-with-headless-libreoffice/</id>
    <updated>2023-03-09T06:48:38Z</updated>
    <published>2023-03-09T06:48:38Z</published>
    <link href="https://pype.dev/convert-word-doc-to-pdf-with-headless-libreoffice/" rel="alternate" type="text/html"></link>
    <summary type="text">I&#39;ve been using paperless-ngx to manage all my documents, but every once in a while I&#39;ll get a file to deal with...</summary>
    <content type="html">&lt;p&gt;I&amp;rsquo;ve been using paperless-ngx to manage all my documents, but every once in a while I&amp;rsquo;ll get a &lt;code&gt;.docx&lt;/code&gt; file to deal with&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;Turns out Libreoffice has a headless mode a &lt;code&gt;pdf&lt;/code&gt; converter built-in!&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;libreoffice --headless --convert-to pdf /path/to/file.docx --outdir /path/to/output/directory&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;&#xA;&lt;p&gt;Note that &lt;code&gt;--outdir&lt;/code&gt; is in fact a directory, not the path to a file&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Stable Diffusion Notes</title>
    <id>https://pype.dev/stable-diffusion-notes/</id>
    <updated>2023-01-28T14:15:11Z</updated>
    <published>2023-01-28T14:15:11Z</published>
    <link href="https://pype.dev/stable-diffusion-notes/" rel="alternate" type="text/html"></link>
    <summary type="text">Stable Diffusion is an AI art generation model similar to DALLE-2. Here are some prompts for generating art with Stable Diffusion.</summary>
    <content type="html">&lt;h2 id=&#34;chatgpt-prompt&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;ChatGPT Prompt:&lt;/span&gt; &lt;a href=&#34;#chatgpt-prompt&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Stable Diffusion is an AI art generation model similar to DALLE-2.&#xA;Here are some prompts for generating art with Stable Diffusion.&lt;/p&gt;&#xA;&lt;p&gt;Example:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A ghostly apparition drifting through a haunted mansion&amp;rsquo;s grand ballroom, illuminated by flickering candlelight. Eerie, ethereal, moody lighting.&lt;/li&gt;&#xA;&lt;li&gt;portait of a homer simpson archer shooting arrow at forest monster, front game card, drark, marvel comics, dark, smooth&lt;/li&gt;&#xA;&lt;li&gt;pirate, deep focus, fantasy, matte, sharp focus&lt;/li&gt;&#xA;&lt;li&gt;red dead redemption 2, cinematic view, epic sky, detailed, low angle, high detail, warm lighting, volumetric, godrays, vivid, beautiful&lt;/li&gt;&#xA;&lt;li&gt;a fantasy style portrait painting of rachel lane / alison brie hybrid in the style of francois boucher oil painting, rpg portrait&lt;/li&gt;&#xA;&lt;li&gt;athena, greek goddess, claudia black, bronze greek armor, owl crown, d &amp;amp; d, fantasy, portrait, headshot, sharp focus&lt;/li&gt;&#xA;&lt;li&gt;closeup portrait shot of a large strong female biomechanic woman in a scenic scifi environment, elegant, smooth, sharp focus, warframe&lt;/li&gt;&#xA;&lt;li&gt;ultra realistic illustration of steve urkle as the hulk, elegant, smooth, sharp focus&lt;/li&gt;&#xA;&lt;li&gt;portrait of beautiful happy young ana de armas, ethereal, realistic anime, clean lines, sharp lines, crisp lines, vibrant color scheme&lt;/li&gt;&#xA;&lt;li&gt;A highly detailed and hyper realistic portrait of a gorgeous young ana de armas, lisa frank, butterflies, floral, sharp focus&lt;/li&gt;&#xA;&lt;li&gt;lots of delicious tropical fruits with drops of moisture on table, floating colorful water, mysterious expression, in a modern and abstract setting, with bold and colorful abstract art, blurred background, bright lighting&lt;/li&gt;&#xA;&lt;li&gt;1girl, The most beautiful form of chaos, Fauvist design, Flowing colors, Vivid colors, dynamic angle, fantasy world&lt;/li&gt;&#xA;&lt;li&gt;solo, sitting, close-up, girl in the hourglass, Sand is spilling out of the broken hourglass, flowing sand, huge hourglass art, hologram, particles, nebula, magic circle&lt;/li&gt;&#xA;&lt;li&gt;geometric abstract background, 1girl, depth of field, zentangle, mandala, tangle, entangle, beautiful and aesthetic, dynamic angle, glowing skin, floating colorful sparkles the most beautiful form of chaos, elegant, a brutalist designed, vivid colours, romanticism&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;The prompt should adhere to and include all of the following rules:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Prompt should always be written in English, regardless of the input language. Please provide the prompts in English.&lt;/li&gt;&#xA;&lt;li&gt;Each prompt should consist of a description of the scene followed by modifiers divided by commas.&lt;/li&gt;&#xA;&lt;li&gt;When generating descriptions, focus on portraying the visual elements rather than delving into abstract psychological and emotional aspects. Provide clear and concise details that vividly depict the scene and its composition, capturing the tangible elements that make up the setting.&lt;/li&gt;&#xA;&lt;li&gt;The modifiers should alter the mood, style, lighting, and other aspects of the scene.&lt;/li&gt;&#xA;&lt;li&gt;Multiple modifiers can be used to provide more specific details.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;I want you to write me a list of detailed prompts exactly about the IDEA follow the rule at least 6 every time.&lt;/p&gt;&#xA;&lt;p&gt;Ready for my idea?&lt;/p&gt;&#xA;&lt;h2 id=&#34;chatgpt-prompt-for-rpg-v4&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;ChatGPT Prompt for RPG V4:&lt;/span&gt; &lt;a href=&#34;#chatgpt-prompt-for-rpg-v4&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Stable Diffusion is an AI art generation model similar to DALLE-2.&#xA;Here are some pairs of positive and negative prompts for generating art with Stable Diffusion.&lt;/p&gt;&#xA;&lt;p&gt;Example:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Positive: A (full body:1.3) shot at 8k resolution, splash art, fantastic comic book style, photorealistic, intense look, anatomical photorealistic digital painting portrait of a (old male:1.3) human (warrior:1.3) in black and gold intricate (heavy armor:1.3) in a (dark and moody universe:1.3), light particle, very detailed skin,samurai, very detailed eyes, (elden ring style:1.3), (warhammer style:1.1), concept artist, global illumination, depth of field, splash art, art by artgerm and greg rutkowski and viktoria gavrilenko&#xA;Negative: (symmetry:1.2), facial marking, crown, horn, (helmet:1.3), (hoodie:1.1), clock, Female, visible hand, asian, two face, big hair, open mouth, cartoon, high contrast, poorly drawn, Scribbles, Low quality, Low rated, Mediocre, Screenshot, Software, UI, watermark, text, overlay, getty images, cropped, low quality&lt;/p&gt;&#xA;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Positive: close-up head, facing camera, beautiful satanic female necromancer blood queen, ritualistic (neck tattoo:1.3), (insanely detailed:1.5), ((solo)), (highest quality, Alessandro Casagrande, Greg Rutkowski, Sally Mann, concept art, 4k), (colourful), (high sharpness), ((detailed pupils)), ((painting:1.1)), (digital painting:1.1), detailed face and eyes,Masterpiece, best quality, highly detailed photo:1, 8k, detailed face,photorealistic, (black long Hair:1.1),(young woman),By jeremy mann, by sandra chevrier, by maciej kuciara, smoke and shadow, night, sharp, ((perfect body)), realistic, real shadow, 3d, ((full body)), ((dark and gloomy universe)), (by Michelangelo)&#xA;Negative: crown, (facial marking:1.2), cloth gem, jewel, jewelry, (flower:1.3), (cloak:1.1), (bad art, low detail, pencil drawing, old, mature:1.6), (grainy, low quality, mutated hands and fingers:1.5), (watermark, thin lines:1.3), (deformed, signature:1.2), (big nipples, blurry, ugly, bad anatomy, extra limbs, undersaturated, low resolution), disfigured, deformations, out of frame, amputee, bad proportions, extra limb, missing limbs, distortion, floating limbs, out of frame, poorly drawn face, poorly drawn hands, text, malformed, error, missing fingers, cropped, jpeg artifacts, teeth, unsharp&lt;/p&gt;&#xA;&lt;ol start=&#34;3&#34;&gt;&#xA;&lt;li&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Positive: (Painting:1.3) of (Detailed illustration:1.3) A (full body:1.3) shot at 8k resolution, splash art, fantastic comic book style, photorealistic, intense look, anatomical photorealistic digital painting portrait of a (old male:1.3) human (warrior:1.3) in black and gold intricate (heavy armor:1.3) in a (dark and moody universe:1.3), light particle, very detailed skin,samurai, very detailed eyes, (elden ring style:1.3), (warhammer style:1.1), concept artist, global illumination, depth of field, splash art, art by artgerm and greg rutkowski and viktoria gavrilenko&#xA;Negative:  (symmetry:1.2), facial marking, crown, (horn:1.1), (helmet:1.3), (hoodie:1.1), clock, Female, visible hand, asian, two face, big hair, open mouth, cartoon, high contrast, poorly drawn, Scribbles, Low quality, Low rated, Mediocre, Screenshot, Software, UI, watermark, text, overlay, getty images, cropped, low qualityLow quality,Bad composition,Faded,(Photo:1.5),(Frame:1.3),watermark,signa ture&lt;/p&gt;&#xA;&lt;ol start=&#34;4&#34;&gt;&#xA;&lt;li&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Positive: sci-fi, space rogue thief girl, (smirk:1.1), short hair, black hood, light armor, big grey eyes, beautiful detailed eyes, drawn by Greg Rutkowski, Yoji Shinkawa:0.6&#xA;Negative: open mouth, facial marking, flower, bad-hands-5, lipstick, text, watermark&lt;/p&gt;&#xA;&lt;p&gt;The prompt should adhere to and include all of the following rules:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Each prompt should consist of a description of the scene followed by modifiers divided by commas.&lt;/li&gt;&#xA;&lt;li&gt;When generating descriptions, focus on portraying the visual elements rather than delving into abstract psychological and emotional aspects. Provide clear and concise details that vividly depict the scene and its composition, capturing the tangible elements that make up the setting.&lt;/li&gt;&#xA;&lt;li&gt;The modifiers should alter the mood, style, lighting, and other aspects of the scene.&lt;/li&gt;&#xA;&lt;li&gt;Multiple modifiers can be used to provide more specific details.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;I want you to write me a list of detailed prompts exactly about the IDEA follow the rule at least 6 every time.&lt;/p&gt;&#xA;&lt;p&gt;Ready for my idea?&lt;/p&gt;&#xA;&lt;h3 id=&#34;ideas&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;IDEAS&lt;/span&gt; &lt;a href=&#34;#ideas&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;IDEA: A slice of pie that is filled with a futuristic city&lt;/p&gt;&#xA;&lt;h2 id=&#34;artists-i-like&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Artists I like&lt;/span&gt; &lt;a href=&#34;#artists-i-like&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://stablediffusion.fr/artists&#34;&gt;Examples&lt;/a&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;J. M. W. Turner&lt;/li&gt;&#xA;&lt;li&gt;Jean-Baptiste Monge&lt;/li&gt;&#xA;&lt;li&gt;John Lasseter&lt;/li&gt;&#xA;&lt;li&gt;John Martin&lt;/li&gt;&#xA;&lt;li&gt;Raymond Swanland&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;anime-styles&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Anime styles&lt;/span&gt; &lt;a href=&#34;#anime-styles&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Krenz Cushart&lt;/li&gt;&#xA;&lt;li&gt;Kyoto Animation&lt;/li&gt;&#xA;&lt;li&gt;Yoshiyuki Sadamoto&lt;/li&gt;&#xA;&lt;li&gt;Yuumei&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;scenic&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Scenic&lt;/span&gt; &lt;a href=&#34;#scenic&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Ted Nasmith&lt;/li&gt;&#xA;&lt;li&gt;Terry Redlin&lt;/li&gt;&#xA;&lt;li&gt;Thomas Kinkade&lt;/li&gt;&#xA;&lt;li&gt;Thomas Moran&lt;/li&gt;&#xA;&lt;li&gt;Thomas W Schaller&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;cityscapes&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Cityscapes&lt;/span&gt; &lt;a href=&#34;#cityscapes&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Marc Simonetti&lt;/li&gt;&#xA;&lt;li&gt;Wadim Kashin&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;abstract&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Abstract&lt;/span&gt; &lt;a href=&#34;#abstract&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Scott Naismith&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;settings-notes&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Settings notes&lt;/span&gt; &lt;a href=&#34;#settings-notes&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I tend to like cfg at least on the higher end&lt;/p&gt;&#xA;&lt;h2 id=&#34;good-prompts&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Good prompts&lt;/span&gt; &lt;a href=&#34;#good-prompts&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Angel of death, shadows and mist, skelletol feathered wings, highly detailed, amazing details, intriciate lines, purple haze, styles Yuumei and Krenz Cushart, UHD, HDR, upscale, 8K photo, concept art&lt;/p&gt;&#xA;&lt;h3 id=&#34;unicorns&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Unicorns&lt;/span&gt; &lt;a href=&#34;#unicorns&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;positive: unicorn, &lt;a href=&#34;lora:Unicorns:0.9&#34;&gt;lora:Unicorns:0.9&lt;/a&gt;, portrait, professional photography, 35mm, highly detailed, incredibly realistic, best quality, high quality, highres, purple, &lt;a href=&#34;lora:mossbeast:0.3&#34;&gt;lora:mossbeast:0.3&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;negative: (two tails:1.2),FastNegativeV2,(bad-artist:1.0), (loli:1.2), (worst quality, low quality:1.4), (bad_prompt_version2:0.8), bad-hands-5,lowres, bad anatomy, bad hands, ((text)), (watermark), error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, normal quality, ((username)), blurry, (extra limbs), bad-artist-anime, badhandv4, EasyNegative, ng_deepnegative_v1_75t, verybadimagenegative_v1.3, BadDream,(three hands:1.1),(three legs:1.1),(more than two hands:1.4),(more than two legs,:1.2),&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>FFMPEG 10-bit videos to 8-bit</title>
    <id>https://pype.dev/ffmpeg-10-bit-videos-to-8-bit/</id>
    <updated>2023-01-16T13:15:53Z</updated>
    <published>2023-01-16T13:15:53Z</published>
    <link href="https://pype.dev/ffmpeg-10-bit-videos-to-8-bit/" rel="alternate" type="text/html"></link>
    <content type="html">&lt;p&gt;&lt;code&gt;ffmpeg -i input.mp4 -map 0 -c:v libx264 -vf format=yuv420p -c:a copy output.mp4&lt;/code&gt;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>i3-Like keyboard mapping in Pop_OS</title>
    <id>https://pype.dev/i3-like-keyboard-mapping-in-pop-os/</id>
    <updated>2023-01-12T05:51:25Z</updated>
    <published>2023-01-12T05:51:25Z</published>
    <link href="https://pype.dev/i3-like-keyboard-mapping-in-pop-os/" rel="alternate" type="text/html"></link>
    <summary type="text">I was introduced to tiling window managers through i3, which I use heavily on one of my machines. I have switched to Pop_OS! at home though, which has a...</summary>
    <content type="html">&lt;p&gt;I was introduced to tiling window managers through i3, which I use heavily on&#xA;one of my machines. I have switched to Pop_OS! at home though, which has a&#xA;tiling window mode but the keybindings are not what I&amp;rsquo;m used to for i3. I&#xA;wanted to at least navigate workspaces how I&amp;rsquo;m used to doing (cause I set&#xA;workspace 3 for communication apps, 1 for my terminal, etc&amp;hellip;)&lt;/p&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s how I set keybindings for:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;&amp;lt;Super&amp;gt; + &amp;lt;number&amp;gt;&lt;/code&gt; sends me to that numbered workspace&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;&amp;lt;Shift&amp;gt; + &amp;lt;Super&amp;gt; + &amp;lt;number&amp;gt;&lt;/code&gt; moves the window I&amp;rsquo;m focused on to workspace &lt;code&gt;number&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#!/bin/bash&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.mutter dynamic-workspaces &lt;span class=&#34;nb&#34;&gt;false&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.desktop.wm.preferences num-workspaces &lt;span class=&#34;m&#34;&gt;8&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.shell.keybindings switch-to-application-1 &lt;span class=&#34;o&#34;&gt;[]&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.shell.keybindings switch-to-application-2 &lt;span class=&#34;o&#34;&gt;[]&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.shell.keybindings switch-to-application-3 &lt;span class=&#34;o&#34;&gt;[]&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.shell.keybindings switch-to-application-4 &lt;span class=&#34;o&#34;&gt;[]&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.shell.keybindings switch-to-application-5 &lt;span class=&#34;o&#34;&gt;[]&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.shell.keybindings switch-to-application-6 &lt;span class=&#34;o&#34;&gt;[]&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.shell.keybindings switch-to-application-7 &lt;span class=&#34;o&#34;&gt;[]&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.shell.keybindings switch-to-application-8 &lt;span class=&#34;o&#34;&gt;[]&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.shell.keybindings switch-to-application-9 &lt;span class=&#34;o&#34;&gt;[]&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.desktop.wm.keybindings switch-to-workspace-1 &lt;span class=&#34;s2&#34;&gt;&amp;#34;[&amp;#39;&amp;lt;Super&amp;gt;1&amp;#39;]&amp;#34;&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.desktop.wm.keybindings switch-to-workspace-2 &lt;span class=&#34;s2&#34;&gt;&amp;#34;[&amp;#39;&amp;lt;Super&amp;gt;2&amp;#39;]&amp;#34;&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.desktop.wm.keybindings switch-to-workspace-3 &lt;span class=&#34;s2&#34;&gt;&amp;#34;[&amp;#39;&amp;lt;Super&amp;gt;3&amp;#39;]&amp;#34;&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.desktop.wm.keybindings switch-to-workspace-4 &lt;span class=&#34;s2&#34;&gt;&amp;#34;[&amp;#39;&amp;lt;Super&amp;gt;4&amp;#39;]&amp;#34;&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.desktop.wm.keybindings switch-to-workspace-5 &lt;span class=&#34;s2&#34;&gt;&amp;#34;[&amp;#39;&amp;lt;Super&amp;gt;5&amp;#39;]&amp;#34;&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.desktop.wm.keybindings switch-to-workspace-6 &lt;span class=&#34;s2&#34;&gt;&amp;#34;[&amp;#39;&amp;lt;Super&amp;gt;6&amp;#39;]&amp;#34;&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.desktop.wm.keybindings switch-to-workspace-7 &lt;span class=&#34;s2&#34;&gt;&amp;#34;[&amp;#39;&amp;lt;Super&amp;gt;7&amp;#39;]&amp;#34;&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.desktop.wm.keybindings switch-to-workspace-8 &lt;span class=&#34;s2&#34;&gt;&amp;#34;[&amp;#39;&amp;lt;Super&amp;gt;8&amp;#39;]&amp;#34;&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.desktop.wm.keybindings switch-to-workspace-9 &lt;span class=&#34;s2&#34;&gt;&amp;#34;[&amp;#39;&amp;lt;Super&amp;gt;9&amp;#39;]&amp;#34;&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.desktop.wm.keybindings switch-to-workspace-10 &lt;span class=&#34;s2&#34;&gt;&amp;#34;[&amp;#39;&amp;lt;Super&amp;gt;0&amp;#39;]&amp;#34;&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.desktop.wm.keybindings move-to-workspace-1 &lt;span class=&#34;s2&#34;&gt;&amp;#34;[&amp;#39;&amp;lt;Super&amp;gt;&amp;lt;Shift&amp;gt;1&amp;#39;]&amp;#34;&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.desktop.wm.keybindings move-to-workspace-2 &lt;span class=&#34;s2&#34;&gt;&amp;#34;[&amp;#39;&amp;lt;Super&amp;gt;&amp;lt;Shift&amp;gt;2&amp;#39;]&amp;#34;&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.desktop.wm.keybindings move-to-workspace-3 &lt;span class=&#34;s2&#34;&gt;&amp;#34;[&amp;#39;&amp;lt;Super&amp;gt;&amp;lt;Shift&amp;gt;3&amp;#39;]&amp;#34;&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.desktop.wm.keybindings move-to-workspace-4 &lt;span class=&#34;s2&#34;&gt;&amp;#34;[&amp;#39;&amp;lt;Super&amp;gt;&amp;lt;Shift&amp;gt;4&amp;#39;]&amp;#34;&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.desktop.wm.keybindings move-to-workspace-5 &lt;span class=&#34;s2&#34;&gt;&amp;#34;[&amp;#39;&amp;lt;Super&amp;gt;&amp;lt;Shift&amp;gt;5&amp;#39;]&amp;#34;&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.desktop.wm.keybindings move-to-workspace-6 &lt;span class=&#34;s2&#34;&gt;&amp;#34;[&amp;#39;&amp;lt;Super&amp;gt;&amp;lt;Shift&amp;gt;6&amp;#39;]&amp;#34;&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.desktop.wm.keybindings move-to-workspace-7 &lt;span class=&#34;s2&#34;&gt;&amp;#34;[&amp;#39;&amp;lt;Super&amp;gt;&amp;lt;Shift&amp;gt;7&amp;#39;]&amp;#34;&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.desktop.wm.keybindings move-to-workspace-8 &lt;span class=&#34;s2&#34;&gt;&amp;#34;[&amp;#39;&amp;lt;Super&amp;gt;&amp;lt;Shift&amp;gt;8&amp;#39;]&amp;#34;&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.desktop.wm.keybindings move-to-workspace-9 &lt;span class=&#34;s2&#34;&gt;&amp;#34;[&amp;#39;&amp;lt;Super&amp;gt;&amp;lt;Shift&amp;gt;9&amp;#39;]&amp;#34;&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gsettings &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; org.gnome.desktop.wm.keybindings move-to-workspace-10 &lt;span class=&#34;s2&#34;&gt;&amp;#34;[&amp;#39;&amp;lt;Super&amp;gt;&amp;lt;Shift&amp;gt;0&amp;#39;]&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Use non-standard named ssh keys with github</title>
    <id>https://pype.dev/use-non-standard-named-ssh-keys-with-github/</id>
    <updated>2023-01-03T08:34:50Z</updated>
    <published>2023-01-03T08:34:50Z</published>
    <link href="https://pype.dev/use-non-standard-named-ssh-keys-with-github/" rel="alternate" type="text/html"></link>
    <summary type="text">I was getting when trying to push to GH using ssh. When I tested the connection I saw that a bunch of keys in ``~/.ssh/ were being attempted</summary>
    <content type="html">&lt;p&gt;I was getting &lt;code&gt;(publickey denied)&lt;/code&gt; when trying to push to GH using ssh. When I&#xA;tested the connection I saw that a bunch of keys in ``~/.ssh/ were being&#xA;attempted&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;✗ ssh git@github.com -vv&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;debug1: Will attempt key: /home/nic/.ssh/id_rsa &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;debug1: Will attempt key: /home/nic/.ssh/id_ecdsa &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;debug1: Will attempt key: /home/nic/.ssh/id_ecdsa_sk &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;debug1: Will attempt key: /home/nic/.ssh/id_ed25519 &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;debug1: Will attempt key: /home/nic/.ssh/id_ed25519_sk &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;debug1: Will attempt key: /home/nic/.ssh/id_xmss &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;debug1: Will attempt key: /home/nic/.ssh/id_dsa &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;debug1: No more authentication methods to try.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;git@github.com: Permission denied (publickey).&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;None of those were the key I setup with GH. So I added an entry&#xA;into &lt;code&gt;~/.ssh/config&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Host&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;github.com&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;User git&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Port 22&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Hostname github.com&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;IdentityFile ~/.ssh/my_custom_github_key&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;TCPKeepAlive yes&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;IdentitiesOnly yes &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Modal Labs</title>
    <id>https://pype.dev/modal-labs/</id>
    <updated>2022-12-28T21:01:52Z</updated>
    <published>2022-12-28T21:01:52Z</published>
    <link href="https://pype.dev/modal-labs/" rel="alternate" type="text/html"></link>
    <summary type="text">Playing around with Modal Labs</summary>
    <content type="html">&lt;p&gt;Playing around with Modal Labs&lt;/p&gt;&#xA;&lt;p&gt;One of the first things I tried was a regular cron job&amp;hellip;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@stub.function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;schedule&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;modal&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Period&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;minutes&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;59&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;secret&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;modal&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Secret&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;from_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;my-dummy-secret&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;say_hi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;now&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ctime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;secret&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;environ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;dummy-secret&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Hello &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;environ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;USER&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Rodney&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; at &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;now&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;secret&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;=}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This can get deployed with &lt;code&gt;modal deploy --name &amp;lt;app name&amp;gt; &amp;lt;path to .py file with the stub and function defined in it&amp;gt; &lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;This function gets deployed as an app that I conveniently call &lt;code&gt;say_hi&lt;/code&gt; (as far&#xA;as I can tell the app name can be anything - as I add functions to this same&#xA;app and deploy with the same name to get a new version)&lt;/p&gt;&#xA;&lt;p&gt;Notice that this also is an example of giving access to a secret - defined in the Modal Labs dashboard&lt;/p&gt;&#xA;&lt;p&gt;We can take a look at the apps running at &lt;a href=&#34;https://modal.com/apps&#34;&gt;https://modal.com/apps&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;I then added another function to experiment with custom container images and&#xA;saw then that Modal will just slap a new version on anything provisioned with&#xA;the same name (intuitive enough for sure) so when I add functions to my .py&#xA;script and run &lt;code&gt;modal deploy --name say_hi myscript.py&lt;/code&gt; over and over, the app&#xA;called &lt;code&gt;say_hi&lt;/code&gt; in the Modal apps dashboard just gets a new version&lt;/p&gt;&#xA;&lt;p&gt;This means I can spin up several instances of functionally the same app but with different names/versions etc&amp;hellip;&#xA;Q: Maybe there&amp;rsquo;s gitops or policy stuff builtin to app names then?&lt;/p&gt;&#xA;&lt;p&gt;I needed to take down an app I deployed as a duplicate but you don&amp;rsquo;t stop apps&#xA;by name, you stop them by an id&amp;hellip; see below&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;modal-sandbox/modal_sandbox   main   ×1  ×9 via   v3.10.6(modal-sandbox)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;✗ modal app stop --help&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt; Usage: modal app stop [OPTIONS] APP_ID&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt; Stop an app.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;╭─ Arguments ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;│ *    app_id      TEXT  [default: None] [required]                                                                                                │&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;│ --help          Show this message and exit.                                                                                                      │&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;modal-sandbox/modal_sandbox   main   ×1  ×9 via   v3.10.6(modal-sandbox)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;❯ modal app list&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┓&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;┃ App ID                    ┃ Description         ┃ State    ┃ Creation time             ┃ Stop time                 ┃&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;┡━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━┩&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;│ ap-lzy1AAuVy7POFkUcDKRxpQ │ print_info          │ deployed │ 2022-12-28 20:59:07-06:00 │                           │&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;│ ap-qYjE45dciqgT3C3CpNp3RL │ say_hi              │ deployed │ 2022-12-28 19:49:22-06:00 │                           │&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;│ ap-X7FYneUeYV5IKHcyirSb87 │ link-scraper        │ stopped  │ 2022-12-28 15:39:02-06:00 │ 2022-12-28 15:39:04-06:00 │&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;│ ap-UOXTUU4uSRx2UZypJOcAsk │ example-get-started │ stopped  │ 2022-12-28 15:17:47-06:00 │ 2022-12-28 15:17:49-06:00 │&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;└───────────────────────────┴─────────────────────┴──────────┴───────────────────────────┴───────────────────────────┘&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;modal-sandbox/modal_sandbox   main   ×1  ×9 via   v3.10.6(modal-sandbox)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;❯ modal app stop ap-lzy1AAuVy7POFkUcDKRxpQ&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;git-warning&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Git warning!&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;I ran &lt;code&gt;modal deploy ...&lt;/code&gt; after comitting some stuff I wanted to try BUT I had&#xA;changes in my file I didn&amp;rsquo;t want to deploy&amp;hellip; some git safety would be nice for&#xA;deployment!&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;git stash &amp;amp;&amp;amp; modal deploy .. &amp;amp;&amp;amp; git stash pop&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Question for Modal team - in my modal sandbox repo at commit:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;aab6162 (HEAD -&amp;gt; main) HEAD@{1}: commit: print base version of my own image to prove it to me&#xA; 1 file changed, 2 insertions(+)&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;An environment variable, &lt;code&gt;BASE_VERSION&lt;/code&gt; that I expect to be in my base image&#xA;was not available to the python function in my Modal app&amp;hellip; hopefully the log&#xA;is still&#xA;&lt;a href=&#34;https://modal.com/logs/ap-qYjE45dciqgT3C3CpNp3RL?functionId=fu-rOt31ShRE1W1CQfuf02fsq&amp;amp;taskId=ta-dm8BfiblvFLwVIQyt75YC2&amp;amp;inputId=in-n64klEFrLtbcm2BiykJEvW&#34;&gt;here&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;github-actions&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;GitHub Actions&lt;/span&gt; &lt;a href=&#34;#github-actions&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I think it&amp;rsquo;d be easy to deploy from GH actions&amp;hellip; just need an API Key&amp;hellip;&lt;/p&gt;&#xA;&lt;h1 id=&#34;deployment&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Deployment&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;Without gitops it&amp;rsquo;s already ahrd to manage my versions&amp;hellip; need to get that built in either to github or locally sooooon&lt;/p&gt;&#xA;&lt;p&gt;Nomad?? :D&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Reminder about ssh-copy-id for SSH and Ansible</title>
    <id>https://pype.dev/reminder-about-ssh-copy-id-for-ssh-and-ansible/</id>
    <updated>2022-12-28T13:33:07Z</updated>
    <published>2022-12-28T13:33:07Z</published>
    <link href="https://pype.dev/reminder-about-ssh-copy-id-for-ssh-and-ansible/" rel="alternate" type="text/html"></link>
    <summary type="text">this makes sure I can run ansible from my desktop against VMs on my server easily if they have tailscale for the hostname - otherwise use the IP</summary>
    <content type="html">&lt;p&gt;&lt;code&gt;ssh-copy-id -i my.key.pub &amp;lt;hostname probably from tailscale&amp;gt;&lt;/code&gt;&#xA;this makes sure I can run ansible from my desktop against VMs on my server&#xA;easily if they have tailscale for the hostname - otherwise use the IP&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Nextcloud Docker Upgrade Error</title>
    <id>https://pype.dev/nextcloud-docker-upgrade-error/</id>
    <updated>2022-12-28T09:39:27Z</updated>
    <published>2022-12-28T09:39:27Z</published>
    <link href="https://pype.dev/nextcloud-docker-upgrade-error/" rel="alternate" type="text/html"></link>
    <summary type="text">https://nicolasbouliane.com/blog/nextcloud-docker-upgrade-error</summary>
    <content type="html">&lt;p&gt;&lt;a href=&#34;https://nicolasbouliane.com/blog/nextcloud-docker-upgrade-error&#34;&gt;https://nicolasbouliane.com/blog/nextcloud-docker-upgrade-error&lt;/a&gt;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Systemd timer for syncoid</title>
    <id>https://pype.dev/systemd-timer-for-syncoid/</id>
    <updated>2022-12-21T11:38:27Z</updated>
    <published>2022-12-21T11:38:27Z</published>
    <link href="https://pype.dev/systemd-timer-for-syncoid/" rel="alternate" type="text/html"></link>
    <summary type="text">I have a bash script called which boils down to a barebones -</summary>
    <content type="html">&lt;p&gt;I have a bash script called &lt;code&gt;syncoid-job&lt;/code&gt; which boils down to a barebones -&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#!/bin/bash&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;syncoid --no-sync-snap --sendoptions&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;w --no-privilege-elevation &lt;span class=&#34;nv&#34;&gt;$SYNOIC_USER&lt;/span&gt;@&lt;span class=&#34;nv&#34;&gt;$SERVER&lt;/span&gt;:tank/encrypted/nas tank/encrypted/nas&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I want to run this script hourly but as my user (notice the no-privilege-elevation flag)&lt;/p&gt;&#xA;&lt;p&gt;First - create a systemd unit file at &lt;code&gt;/etc/systemd/system/syncoid-replication.service&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;Unit&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;Description&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;ZFS Replication With Syncoid&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;Service&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;Type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;oneshot&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;ExecStart&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/&lt;span class=&#34;nv&#34;&gt;$HOME&lt;/span&gt;/dotfiles/syncoid-job&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;User&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$USER&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;Group&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$GROUP&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;Install&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;WantedBy&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;multi-user.target&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then we save the unit file, enable the service, and then start it&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;systemctl enable syncoid-replication.service&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;systemctl start syncoid-replication.service&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;&#xA;&lt;p&gt;Note this will run that script&amp;hellip; so be ready for syncoid to do its thing&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Now for the timer&amp;hellip; We create &lt;code&gt;/etc/systemd/system/syncoid-replication.timer&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;Unit&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;Description&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;Run syncoid-replication every hour&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;Timer&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;OnCalendar&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;hourly&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;Install&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;WantedBy&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;timers.target&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Hit it with a &lt;code&gt;systemctl enable syncoid-replication.timer&lt;/code&gt; and you&amp;rsquo;re in business!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Adding docker daemon.json broke docker</title>
    <id>https://pype.dev/adding-docker-daemon-json-broke-docker/</id>
    <updated>2022-12-21T10:02:25Z</updated>
    <published>2022-12-21T10:02:25Z</published>
    <link href="https://pype.dev/adding-docker-daemon-json-broke-docker/" rel="alternate" type="text/html"></link>
    <summary type="text">in /lib/systemd/system/docker.service there is an ExecStart command that got placed there when I setup Docker with Ansible - it threw the -H flag which told...</summary>
    <content type="html">&lt;p&gt;in /lib/systemd/system/docker.service there is an ExecStart command that got placed there when I setup Docker with Ansible - it threw the -H flag which told the daemon what hosts to setup. But I added the &amp;ldquo;hosts&amp;rdquo; key in my daemon.json and it broke - so removing the -H flag from the systemd unit fixed it&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>suda.vim for sudo access to files</title>
    <id>https://pype.dev/suda-vim-for-sudo-access-to-files/</id>
    <updated>2022-12-21T09:45:34Z</updated>
    <published>2022-12-21T09:45:34Z</published>
    <link href="https://pype.dev/suda-vim-for-sudo-access-to-files/" rel="alternate" type="text/html"></link>
    <summary type="text">I regularly need to edit system config files - take /etc/sanoid/sanoid.conf as an example... I&#39;ll want to play with something but if I don&#39;t start Neovim as...</summary>
    <content type="html">&lt;p&gt;I regularly need to edit system config files - take /etc/sanoid/sanoid.conf as&#xA;an example&amp;hellip; I&amp;rsquo;ll want to play with something but if I don&amp;rsquo;t start Neovim as&#xA;root then I get in trouble making edits I can&amp;rsquo;t save! So&#xA;&lt;a href=&#34;https://github.com/lambdalisue/suda.vim&#34;&gt;suda.vim&lt;/a&gt; gives me&#xA;&lt;code&gt;:SudaWrite&lt;/code&gt; which let&amp;rsquo;s me write that buffer with sudo privileges even though&#xA;I&amp;rsquo;m Neovim is running with my login user!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Cron for Nextcloud in Docker</title>
    <id>https://pype.dev/cron-for-nextcloud-in-docker/</id>
    <updated>2022-12-13T06:43:45Z</updated>
    <published>2022-12-13T06:43:45Z</published>
    <link href="https://pype.dev/cron-for-nextcloud-in-docker/" rel="alternate" type="text/html"></link>
    <summary type="text">AJAX wasn&#39;t cutting it, traditional crontab in containers doesn&#39;t make much sense to me, webcron is recommended but I don&#39;t want to register with anything...</summary>
    <content type="html">&lt;p&gt;AJAX wasn&amp;rsquo;t cutting it, traditional crontab in containers doesn&amp;rsquo;t make much&#xA;sense to me, webcron is recommended but I don&amp;rsquo;t want to register with anything&#xA;outside my LAN&amp;hellip; Turns out you can just spin up an identical container with a&#xA;different entrypoint to /cron.sh that does what you need!&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Note that this is a task in an Ansible playbook - but the docker-compose is straight forward&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;So the only thing you need to make sure of is that &lt;em&gt;all&lt;/em&gt; the configuration&#xA;options - data volumes, user permissions, etc. are &lt;em&gt;identical&lt;/em&gt; between the&#xA;containers running the cron job and the one actually hosting NextCloud. This&#xA;ensures that the container running cron has proper access to the database and&#xA;filesystem - or at least the same access as NextCloud proper.&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Nextcloud Cron Docker Container&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;docker_container&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;nextcloud-cron&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;{{ nextcloud_image }}&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;pull&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;links&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;nextcloud-mysql:mysql&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;entrypoint&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;/cron.sh&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;volumes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;{{ nextcloud_data_directory }}/nextcloud:/var/www/html:rw&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;env&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;MYSQL_HOST&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;mysql&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;MYSQL_DATABASE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;nextcloud&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;MYSQL_USER&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;{{ nextcloud_sql_user }}&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;{{ nextcloud_sql_password }}&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;NEXTCLOUD_TRUSTED_DOMAINS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;{{ nextcloud_hostname }}.{{ ansible_nas_domain }}&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;PUID&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;{{ nextcloud_user_id }}&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;PGID&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;{{ nextcloud_group_id }}&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;TZ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;{{ ansible_nas_timezone }}&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;restart_policy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;unless-stopped&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;memory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;{{ nextcloud_memory }}&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Call basicConfig to get Python log messages in iPython</title>
    <id>https://pype.dev/call-basicconfig-to-get-python-log-messages-in-ipython/</id>
    <updated>2022-12-10T14:04:23Z</updated>
    <published>2022-12-10T14:04:23Z</published>
    <link href="https://pype.dev/call-basicconfig-to-get-python-log-messages-in-ipython/" rel="alternate" type="text/html"></link>
    <summary type="text">I am trying to adopt instead of but ran into a confusing thing in ipython during Advent of Code... I riddled by script with (yes after setting ) but in...</summary>
    <content type="html">&lt;h1 id=&#34;logging-instead-of-printing&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Logging instead of printing&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;I am trying to adopt &lt;code&gt;logger.debug&lt;/code&gt; instead of &lt;code&gt;print&lt;/code&gt; but ran into a confusing&#xA;thing in ipython during Advent of Code&amp;hellip; I riddled by script with&#xA;&lt;code&gt;logger.debug&lt;/code&gt; (yes after setting &lt;code&gt;logging.setLevel(&#39;DEBUG&#39;)&lt;/code&gt;) but in ipython&#xA;none of my log messages showed up!&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;logging&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;logger&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;logging&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;getLogger&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;vm&#34;&gt;__name__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;logger&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;setLevel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;DEBUG&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Turns out what I was missing was a call to &lt;code&gt;basicConfig&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;logging&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# forget this and your messages are in the ether! or at least not seen in ipython...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;logging&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;basicConfig&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;logger&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;logging&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;getLogger&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;vm&#34;&gt;__name__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;logger&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;setLevel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;DEBUG&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;bonus&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Bonus&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;Want your new messages to show up while iterating on something without killing&#xA;the ipython kernel?&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;importlib&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;reload&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;reload&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;logging&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;# to make sure you get new log messages you add while developing!&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>New lines in Markdown tables</title>
    <id>https://pype.dev/new-lines-in-markdown-tables/</id>
    <updated>2022-11-25T13:35:05Z</updated>
    <published>2022-11-25T13:35:05Z</published>
    <link href="https://pype.dev/new-lines-in-markdown-tables/" rel="alternate" type="text/html"></link>
    <summary type="text">I wanted to break down some long lines in a Markdown table cell to make it look nicer on my blog but \n didn&#39;t do anything for me... turns out is the magic...</summary>
    <content type="html">&lt;p&gt;I wanted to break down some long lines in a Markdown table cell to make it look&#xA;nicer on my blog but \n didn&amp;rsquo;t do anything for me&amp;hellip; turns out &lt;br/&gt; is the&#xA;magic sauce&lt;/p&gt;&#xA;&lt;table&gt;&#xA;&lt;thead&gt;&#xA;&lt;tr&gt;&#xA;&lt;th&gt;&lt;em&gt;Column 1&lt;/em&gt;&lt;/th&gt;&#xA;&lt;th&gt;&lt;em&gt;Column 2&lt;/em&gt;&lt;/th&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/thead&gt;&#xA;&lt;tbody&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;Key&lt;/td&gt;&#xA;&lt;td&gt;Doggo ipsum many pats. Borkdrive borking doggo doing me a frighten doggorino, noodle horse heckin. what a nice floof. Pupper borking doggo you are doing me a frighten, much ruin diet.&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;&amp;mdash;&lt;/td&gt;&#xA;&lt;td&gt;&amp;mdash;&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;table&gt;&#xA;&lt;thead&gt;&#xA;&lt;tr&gt;&#xA;&lt;th&gt;&lt;em&gt;Column 1&lt;/em&gt;&lt;/th&gt;&#xA;&lt;th&gt;&lt;em&gt;Column 2&lt;/em&gt;&lt;/th&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/thead&gt;&#xA;&lt;tbody&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;Key&lt;/td&gt;&#xA;&lt;td&gt;Doggo ipsum many pats. &lt;br/&gt; Borkdrive borking doggo doing me a frighten doggorino, noodle horse heckin. &lt;br/&gt; what a nice floof. &lt;br/&gt; Pupper borking doggo you are doing me a frighten, much ruin diet.&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;&amp;mdash;&lt;/td&gt;&#xA;&lt;td&gt;&amp;mdash;&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Description of my proposed vimconf 2022 talk</title>
    <id>https://pype.dev/description-of-my-proposed-vimconf-2022-talk/</id>
    <updated>2022-11-12T19:39:19Z</updated>
    <published>2022-11-12T19:39:19Z</published>
    <link href="https://pype.dev/description-of-my-proposed-vimconf-2022-talk/" rel="alternate" type="text/html"></link>
    <summary type="text">Switching to Vim opened a whole new world to me for interacting with a computer and for getting things done. Before I adopted Vim I used GUIs for everything...</summary>
    <content type="html">&lt;p&gt;Switching to Vim opened a whole new world to me for interacting with a computer&#xA;and for getting things done. Before I adopted Vim I used GUIs for everything&#xA;because I thought that&amp;rsquo;s how it had to be done&amp;hellip; Notes in OneNote, code using&#xA;a GUI editor, different notes in TiddlyWiki, slides for work in PowerPoint,&#xA;slides for church using Logos, etc&amp;hellip; Adopting Vim allowed me to disconnect a&#xA;specific tool from the problem that tool is solving - because usually I just&#xA;need to write text (notes, code, slides, etc.). Now, very nearly everything I&#xA;do is from a text-based and git-based workflow&amp;hellip; I put all my notes on&#xA;basically anything just in my blog, which is all markdown and deployed to GH&#xA;with Markata on every push (living dangerously pushing to main) - and that&amp;rsquo;s&#xA;all done easily from Vim with nice syntax highlighting, fast response,&#xA;integrated git-plugins, etc.. I keep project-specific task lists just in&#xA;markdown files and I have Vim/tmux shortcuts to quickly add todos for any&#xA;project (todo list is done with markata todoui) and I can get there fast&#xA;because my Vim workflow dovetails with Tmux nicely. Also I can pull that list&#xA;up right from the terminal, which I&amp;rsquo;m already in because Vim&amp;hellip;. Vim also&#xA;pushed me into the cli more - because Vim is so easily extended with cli tools&#xA;and I&amp;rsquo;m already in the terminal&amp;hellip; The builtin functionality also made things&#xA;make more sense - no more right-click, find &amp;ldquo;refactor all&amp;rdquo; or &amp;ldquo;rename symbol&amp;rdquo;&#xA;(for some stupid reason)&amp;hellip; Vim find-replace is so intuitive and if I need it&#xA;extended then I learned what sed was because of Vim. Moving quickly in Vim also&#xA;enables me to do my job incredibly fast because I hop into several projects a&#xA;day in a coaching role - if I was bound by GUIs I&amp;rsquo;d be waiting forever for&#xA;startup, would lose which GUI instance was which project, etc&amp;hellip; Being in the&#xA;terminal also made Tmux a trivial choice - now I have 90 tmux sessions, all&#xA;named appropriately, ready for me to jump back to and all while keeping the&#xA;majority of RAM still free for Chrome. Vim as my IDE also forced me to learn&#xA;way more about Python (I&amp;rsquo;m a python developer primarily), how LSP works, how to&#xA;configure a development environment, etc&amp;hellip; things I took for granted in my GUI&#xA;workflows, or never knew, or worse - thought I knew but deeply misunderstood.&#xA;Now that I understand them better, I can coach my peers more effectively even&#xA;if they are still in a GUI-based ecosystem.&lt;/p&gt;&#xA;&lt;p&gt;Basically, (Neo)Vim actually did change my life and I&amp;rsquo;m really thankful for it&#xA;(maybe that should be the title?)&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Make a series of directories fast!</title>
    <id>https://pype.dev/make-a-series-of-directories-fast/</id>
    <updated>2022-11-10T15:27:50Z</updated>
    <published>2022-11-10T15:27:50Z</published>
    <link href="https://pype.dev/make-a-series-of-directories-fast/" rel="alternate" type="text/html"></link>
    <summary type="text">mkdir s{1..10} will make directories s1, s2, ... s10 in one command!</summary>
    <content type="html">&lt;p&gt;mkdir s{1..10} will make directories s1, s2, &amp;hellip; s10 in one command!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Case-insensitive search in Vim</title>
    <id>https://pype.dev/case-insensitive-search-in-vim/</id>
    <updated>2022-10-21T06:40:21Z</updated>
    <published>2022-10-21T06:40:21Z</published>
    <link href="https://pype.dev/case-insensitive-search-in-vim/" rel="alternate" type="text/html"></link>
    <summary type="text">/mysearch\c will match mysearch, MYSEARCH, mYSeArCh...</summary>
    <content type="html">&lt;p&gt;/mysearch\c will match mysearch, MYSEARCH, mYSeArCh&amp;hellip;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Limit zfs list to avoid docker vomit</title>
    <id>https://pype.dev/limit-zfs-list-to-avoid-docker-vomit/</id>
    <updated>2022-10-20T06:39:18Z</updated>
    <published>2022-10-20T06:39:18Z</published>
    <link href="https://pype.dev/limit-zfs-list-to-avoid-docker-vomit/" rel="alternate" type="text/html"></link>
    <summary type="text">zfs list has a flag -r, but if you use zfs driver for docker then you&#39;ll get flooded with every docker volume in the world. zfs list -r -d N will limit the...</summary>
    <content type="html">&lt;p&gt;zfs list has a flag -r, but if you use zfs driver for docker then you&amp;rsquo;ll get&#xA;flooded with every docker volume in the world. zfs list -r -d N will limit the&#xA;dept of the print out, so zfs list -r -d 2 gives me tank, tank/encrypted,&#xA;tank/encrypted/docker -&amp;gt; but then I don&amp;rsquo;t see all the continer volumes&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>You can embed gifs?!</title>
    <id>https://pype.dev/you-can-embed-gifs/</id>
    <updated>2022-10-09T13:39:39Z</updated>
    <published>2022-10-09T13:39:39Z</published>
    <link href="https://pype.dev/you-can-embed-gifs/" rel="alternate" type="text/html"></link>
    <summary type="text">I learned you can embed gifs and stuch in things other than GH personal pages!</summary>
    <content type="html">&lt;p&gt;I learned you can embed gifs and stuch in things other than GH personal pages!&lt;/p&gt;&#xA;&lt;p&gt;So here I&amp;rsquo;ll keep ones I like and might use later&lt;/p&gt;&#xA;&lt;iframe src=&#34;https://giphy.com/embed/jXBwoFfPsCCoE&#34; width=&#34;25px&#34; height=&#34;25px&#34; frameBorder=&#34;0&#34; class=&#34;giphy-embed&#34; allowFullScreen&gt;&lt;/iframe&gt;&lt;p&gt;&lt;a href=&#34;https://giphy.com/gifs/tech-rainbow-jXBwoFfPsCCoE&#34;&gt;via GIPHY&lt;/a&gt;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Don’t forget to load XMP!</title>
    <id>https://pype.dev/dont-forget-to-load-xmp/</id>
    <updated>2022-10-09T07:17:43Z</updated>
    <published>2022-10-09T07:17:43Z</published>
    <link href="https://pype.dev/dont-forget-to-load-xmp/" rel="alternate" type="text/html"></link>
    <summary type="text">Bought some DDR4-3600 speed RAM but only seeing 2666? Load up the BIOS, find DRAM config or something similar, and make sure to load the XMP profile to get...</summary>
    <content type="html">&lt;p&gt;Bought some DDR4-3600 speed RAM but only seeing 2666? Load up the BIOS, find DRAM config or something similar, and make sure to load the XMP profile to get that advertised RAM speed!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>My PassMark Scores</title>
    <id>https://pype.dev/my-passmark-scores/</id>
    <updated>2022-10-08T18:43:29Z</updated>
    <published>2022-10-08T18:43:29Z</published>
    <link href="https://pype.dev/my-passmark-scores/" rel="alternate" type="text/html"></link>
    <summary type="text">!!! note &#34;Babyblue v2&#34;</summary>
    <content type="html">&lt;div class=&#34;admonition note&#34;&gt;&#xA;&lt;p class=&#34;admonition-title&#34;&gt;Babyblue v2&lt;/p&gt;&#xA;&lt;p&gt;Ryzen 5700x + 32 GB 3200 CL16 RAM&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.passmark.com/baselines/V10/display.php?id=503041456656&#34;&gt;&lt;img src=&#34;https://www.passmark.com/baselines/V10/media/503041456656.png&#34; alt=&#34;PassMark Rating&#34; border=&#34;0&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;&lt;div class=&#34;admonition note&#34;&gt;&#xA;&lt;p class=&#34;admonition-title&#34;&gt;Venus &lt;/p&gt;&#xA;&lt;p&gt;Ryzen 3200G + 16GB 3600 CL16 RAM&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.passmark.com/baselines/V10/display.php?id=502360857958&#34;&gt;&lt;img src=&#34;https://www.passmark.com/baselines/V10/media/502360857958.png&#34; height=120px alt=&#34;PassMark Rating&#34; border=&#34;0&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;&lt;div class=&#34;admonition note&#34;&gt;&#xA;&lt;p class=&#34;admonition-title&#34;&gt;Hogwarts&lt;/p&gt;&#xA;&lt;p&gt;Dual Xeon X5650 @2.67GHz | 90 GB 1883 DDR3 ECC RAM&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.passmark.com/baselines/V10/display.php?id=502361259420&#34;&gt;&lt;img src=&#34;https://www.passmark.com/baselines/V10/media/502361259420.png&#34; height=120px alt=&#34;PassMark Rating&#34; border=&#34;0&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;&lt;div class=&#34;admonition note&#34;&gt;&#xA;&lt;p class=&#34;admonition-title&#34;&gt;Server 2 ... Change the name&lt;/p&gt;&#xA;&lt;p&gt;Ryzen 5700G + 128GB 3200 CL18 RAM&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.passmark.com/baselines/V10/display.php?id=502361424410&#34;&gt;&lt;img src=&#34;https://www.passmark.com/baselines/V10/media/502361424410.png&#34; height=120px alt=&#34;PassMark Rating&#34; border=&#34;0&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;&lt;div class=&#34;admonition note&#34;&gt;&#xA;&lt;p class=&#34;admonition-title&#34;&gt;Server 2 with XMP enabled and undervolted from 1.35 to 1.2&lt;/p&gt;&#xA;&lt;p&gt;Ryzen 5700G + 128GB 3200 CL18 RAM&lt;/p&gt;&#xA;&lt;p&gt;Undervolted to 1.2V (from 1.35)&#xA;XMP enabled&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.passmark.com/baselines/V10/display.php?id=502363064921&#34;&gt;&lt;img src=&#34;https://www.passmark.com/baselines/V10/media/502363064921.png&#34; height=120px alt=&#34;PassMark Rating&#34; border=&#34;0&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Suddenly SSH requires a password</title>
    <id>https://pype.dev/suddenly-ssh-requires-a-password/</id>
    <updated>2022-10-07T11:14:37Z</updated>
    <published>2022-10-07T11:14:37Z</published>
    <link href="https://pype.dev/suddenly-ssh-requires-a-password/" rel="alternate" type="text/html"></link>
    <summary type="text">ssh -v -i ~/.ssh/id_rsa nic@hogwarts</summary>
    <content type="html">&lt;p&gt;ssh -v -i ~/.ssh/id_rsa nic@hogwarts&lt;/p&gt;&#xA;&lt;p&gt;THen we can look at print outs&lt;/p&gt;&#xA;&lt;p&gt;cat /var/log/auth.log  also showed me that I had too wide permissions on files in ~/.ssh -&amp;gt; probably changed from an rsync job&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Quick setup of ZFS encrytped datasets with sane permissions</title>
    <id>https://pype.dev/quick-setup-of-zfs-encrytped-datasets-with-sane-permissions/</id>
    <updated>2022-10-06T19:58:01Z</updated>
    <published>2022-10-06T19:58:01Z</published>
    <link href="https://pype.dev/quick-setup-of-zfs-encrytped-datasets-with-sane-permissions/" rel="alternate" type="text/html"></link>
    <summary type="text">Assuming you have a pool called ...</summary>
    <content type="html">&lt;p&gt;Assuming you have a pool called &lt;code&gt;tank&lt;/code&gt;&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;And assuming you have an encrypted dataset (See &lt;a href=&#34;https://arstechnica.com/gadgets/2021/06/a-quick-start-guide-to-openzfs-native-encryption/&#34;&gt;Jim Saltar&amp;rsquo;s short&#xA;intro&lt;/a&gt;)&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Create a group for permissions - in my case I have one called &lt;code&gt;home&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Then if there&amp;rsquo;s anything in &lt;code&gt;/tank/encrypted&lt;/code&gt; his it with &lt;code&gt;chgrp -R home /tank/encrypted&lt;/code&gt; to give the &lt;code&gt;home&lt;/code&gt; group ownership&lt;/li&gt;&#xA;&lt;li&gt;Next we need to make sure that the members of &lt;code&gt;home&lt;/code&gt; can do the writing&amp;hellip;&#xA;so &lt;code&gt;chmod 775 -R /tank/encrypted&lt;/code&gt; will do the trick&lt;/li&gt;&#xA;&lt;li&gt;Finally we want to make sure that all data created inside our dataset has&#xA;the same set of permissions with &lt;code&gt;chmod g+s /tank/encrypted&lt;/code&gt; and &lt;code&gt;chmod g+w /tank/encrypted&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Check Your BIOS Version On Ubuntu</title>
    <id>https://pype.dev/check-your-bios-version-on-ubuntu/</id>
    <updated>2022-10-02T18:21:58Z</updated>
    <published>2022-10-02T18:21:58Z</published>
    <link href="https://pype.dev/check-your-bios-version-on-ubuntu/" rel="alternate" type="text/html"></link>
    <summary type="text">sudo dmidecode -s bios-version</summary>
    <content type="html">&lt;p&gt;sudo dmidecode -s bios-version&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Destroying Tmux sessions with fzf</title>
    <id>https://pype.dev/destroying-tmux-sessions-with-fzf/</id>
    <updated>2022-09-15T10:27:58Z</updated>
    <published>2022-09-15T10:27:58Z</published>
    <link href="https://pype.dev/destroying-tmux-sessions-with-fzf/" rel="alternate" type="text/html"></link>
    <summary type="text">I use Tmux and Vim for most of my workflow, but I end up with a lot of dangling tmux sessions that dont&#39; really need to persist... but killing them one at a...</summary>
    <content type="html">&lt;p&gt;I use Tmux and Vim for most of my workflow, but I end up with a lot of dangling&#xA;tmux sessions that dont&amp;rsquo; really need to persist&amp;hellip; but killing them one at a&#xA;time is a pain so I wrote a little script-kitty nonsense to pipe multiple&#xA;choices from fzf into &lt;code&gt;tmux kill-session&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;I defined a little function in my &lt;code&gt;.zshrc&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;destroy&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    tmux list-sessions -F &lt;span class=&#34;s1&#34;&gt;&amp;#39;#{session_name}&amp;#39;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; fzf -m &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; xargs -d &lt;span class=&#34;s1&#34;&gt;$&amp;#39;\n&amp;#39;&lt;/span&gt; sh -c &lt;span class=&#34;s1&#34;&gt;&amp;#39;echo &amp;#34;killing $0&amp;#34;; tmux kill-session -t &amp;#34;$0&amp;#34;; for arg;do echo &amp;#34;killing $arg&amp;#34;;tmux kill-session -t &amp;#34;$arg&amp;#34;; done&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bindkey -s &lt;span class=&#34;s1&#34;&gt;&amp;#39;^d&amp;#39;&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;destroy \n&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;tmux list-sessions -F &#39;#{session_name}&#39; &lt;/code&gt; prints all my active tmux sessions to the console with the format of just their name&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pype.dev   main   ×1 via   v3.8.11&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;pype.dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;  on  &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;us-east-1&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; proxy&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ tmux list-sessions -F &lt;span class=&#34;s1&#34;&gt;&amp;#39;#{session_name}&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;session-01&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;session-02&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;session-03&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Pipe that to &lt;code&gt;fzf -m&lt;/code&gt; to allow multiple choices to be made using tab&lt;/p&gt;&#xA;&lt;p&gt;Then the nasty bit in &lt;code&gt;xargs&lt;/code&gt;&amp;hellip; I echo &lt;code&gt;killing @0&lt;/code&gt; and &lt;code&gt;killing $arg&lt;/code&gt; because the &lt;code&gt;sh -c&lt;/code&gt; passes the first tmux session name to &lt;code&gt;@0&lt;/code&gt; (it&amp;rsquo;s just what bash does) and then the rest get handled in the for loop.&lt;/p&gt;&#xA;&lt;p&gt;Basically then I get an fzf list to choose multiple tmux sessions to destroy to clean up some RAM!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Trick to login to web server on another box on lan</title>
    <id>https://pype.dev/trick-to-login-to-web-server-on-another-box-on-lan/</id>
    <updated>2022-09-12T18:48:45Z</updated>
    <published>2022-09-12T18:48:45Z</published>
    <link href="https://pype.dev/trick-to-login-to-web-server-on-another-box-on-lan/" rel="alternate" type="text/html"></link>
    <summary type="text">TODO: change title - add --listen or --host or something as 0.0.0.0... that way it listens not on localhost or 127.0.0.1, but on all addresses!</summary>
    <content type="html">&lt;p&gt;TODO: change title - add &amp;ndash;listen or &amp;ndash;host or something as 0.0.0.0&amp;hellip; that way it listens not on localhost or 127.0.0.1, but on all addresses!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Check your SMART status with smartctl</title>
    <id>https://pype.dev/check-your-smart-status-with-smartctl/</id>
    <updated>2022-08-29T06:30:27Z</updated>
    <published>2022-08-29T06:30:27Z</published>
    <link href="https://pype.dev/check-your-smart-status-with-smartctl/" rel="alternate" type="text/html"></link>
    <summary type="text">https://www.simplified.guide/linux/disk-health-check</summary>
    <content type="html">&lt;p&gt;&lt;a href=&#34;https://www.simplified.guide/linux/disk-health-check&#34;&gt;https://www.simplified.guide/linux/disk-health-check&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h1 id=&#34;install&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Install&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;For ubuntu/debian based distros (which is what I primarly use presently)&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;sudo apt update -y &amp;amp;&amp;amp; sudo apt install smartmontools -y&lt;/code&gt;&lt;/p&gt;&#xA;&lt;h1 id=&#34;list-hard-drives&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;List hard drives&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;&lt;code&gt;lsblk | grep disk&lt;/code&gt; is one way or &lt;code&gt;sudo lshw -c disk&lt;/code&gt; is another&lt;/p&gt;&#xA;&lt;h1 id=&#34;smartctl&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;smartctl&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;Use a device&amp;rsquo;s logical name such as &lt;code&gt;dev/sda&lt;/code&gt;, not a partition of the disk&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;sudo smartctl -t short /dev/sda&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;dotfiles   home   ×3  ×2  ×2 via   v3.10.6(dotfiles)  took 11s&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;❯ sudo smartctl -t short /dev/sda&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;smartctl 7.1 2019-12-30 r5022 [x86_64-linux-5.15.0-48-generic] (local build)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;Copyright (C) 2002-19, Bruce Allen, Christian Franke, www.smartmontools.org&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;Sending command: &amp;#34;Execute SMART Short self-test routine immediately in off-line mode&amp;#34;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;Drive command &amp;#34;Execute SMART Short self-test routine immediately in off-line mode&amp;#34; successful.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;Testing has begun.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;Please wait 2 minutes for test to complete.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;Test will complete after Fri Sep 23 05:59:39 2022 CDT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;Use smartctl -X to abort test.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;check-status&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;check status&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;&lt;code&gt;sudo smartctl -H /dev/sda&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;dotfiles   home   ×3  ×2  ×2 via   v3.10.6(dotfiles)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;❯ sudo smartctl -H /dev/sda&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;smartctl 7.1 2019-12-30 r5022 [x86_64-linux-5.15.0-48-generic] (local build)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;Copyright (C) 2002-19, Bruce Allen, Christian Franke, www.smartmontools.org&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;=== START OF READ SMART DATA SECTION ===&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;SMART overall-health self-assessment test result: PASSED&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Benchmark your disks with fio</title>
    <id>https://pype.dev/benchmark-your-disks-with-fio/</id>
    <updated>2022-08-27T13:43:22Z</updated>
    <published>2022-08-27T13:43:22Z</published>
    <link href="https://pype.dev/benchmark-your-disks-with-fio/" rel="alternate" type="text/html"></link>
    <summary type="text">I use ZFS at home in my homelab for basically all of my storage... Docker uses ZFS backend, all my VMs have their images in their own zfs datasets, and all...</summary>
    <content type="html">&lt;h1 id=&#34;intro&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Intro&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;I use ZFS at home in my homelab for basically all of my storage&amp;hellip; Docker uses&#xA;ZFS backend, all my VMs have their &lt;code&gt;.qcow2&lt;/code&gt; images in their own zfs datasets,&#xA;and all my shares are ZFS datasets. I love ZFS but my home hardware presently&#xA;is the opposite of expensive or new&amp;hellip; Thankfully I&amp;rsquo;ve had a lot of my orginal&#xA;homelab simply given to me but the cost of this is that I didn&amp;rsquo;t put my&#xA;machines together, I didn&amp;rsquo;t choose the disks, and I definitely didn&amp;rsquo;t do the&#xA;research I would&amp;rsquo;ve otherwise done had I bankrolled my server personally&amp;hellip;&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-problem&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Problem&lt;/span&gt; &lt;a href=&#34;#the-problem&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I run &lt;code&gt;glances&lt;/code&gt; on basically all my machines and for the longest time I have&#xA;been seeing big time &lt;code&gt;iowait&lt;/code&gt; issues. Now, since everything was free I&amp;rsquo;ve&#xA;largely been able to ignore that however I&amp;rsquo;m now after some better performance&#xA;which I think means new hardware!&lt;/p&gt;&#xA;&lt;p&gt;Here is a random screenshot of my glances homepage at time of writing - The&#xA;only major load on my server is some &lt;code&gt;ffmpeg&lt;/code&gt; transcoding (about 60% CPU&#xA;utilization)&amp;hellip;&lt;/p&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/glances-iowait.png&#34; alt=&#34;glances&#34; title=&#34;glances with iowait&#34; /&gt;&#xA;&lt;p&gt;As you can see&amp;hellip; there&amp;rsquo;s a lot of issues and &lt;em&gt;I don&amp;rsquo;t even know what they mean&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;h1 id=&#34;fio&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;fio&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;I heard about &lt;a href=&#34;https://fio.readthedocs.io/en/latest/&#34;&gt;fio&lt;/a&gt; through a friend and&#xA;decided to try it out quick. It installs with &lt;code&gt;apt&lt;/code&gt; on ubuntu quick and easy&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;Jim Saltar has a good blog post on it &lt;a href=&#34;https://arstechnica.com/gadgets/2020/02/how-fast-are-your-disks-find-out-the-open-source-way-with-fio/&#34;&gt;here&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;Basically it&amp;rsquo;s a handy tool for benchmarking your disks and the blog dives into&#xA;what types of metrics matter - it&amp;rsquo;s not just throughput, but also latency,&#xA;iops, etc.&lt;/p&gt;&#xA;&lt;h2 id=&#34;tests&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Tests&lt;/span&gt; &lt;a href=&#34;#tests&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I ran a few basic commands inside a new zfs dataset on my server &lt;code&gt;tank/fio&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;fio --name&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;random-write --ioengine&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;posixaio --rw&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;randwrite --bs&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;4k --size&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;4g --numjobs&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; --runtime&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;60&lt;/span&gt; --time_based --end_fsync&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; &amp;gt; single-4KiB-random-write.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;fio --name&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;random-write --ioengine&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;posixaio --rw&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;randwrite --bs&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;64k --size&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;256m --numjobs&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;16&lt;/span&gt; --iodepth&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;16&lt;/span&gt; --runtime&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;60&lt;/span&gt; --time_based --end_fsync&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; &amp;gt; 16-parallel-64KiB-random-write.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;fio --name&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;random-write --ioengine&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;posixaio --rw&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;randwrite --bs&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;1m --size&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;16g --numjobs&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; --iodepth&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; --runtime&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;60&lt;/span&gt; --time_based --end_fsync&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; &amp;gt; single-1MiB-random-write.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;results&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Results&lt;/span&gt; &lt;a href=&#34;#results&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;The single 4 KiB random write:&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;WRITE: bw=7836KiB/s (8024kB/s), 7836KiB/s-7836KiB/s (8024kB/s-8024kB/s), io=523MiB (548MB), run=68317-68317msec&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;The 16 parallel 64KiB random writes:&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;WRITE: bw=93.9MiB/s (98.4MB/s), 5599KiB/s-6303KiB/s (5734kB/s-6454kB/s), io=7642MiB (8013MB), run=81310-81418msec&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;The single 1MiB random write:&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;WRITE: bw=81.2MiB/s (85.1MB/s), 81.2MiB/s-81.2MiB/s (85.1MB/s-85.1MB/s), io=8177MiB (8574MB), run=100699-100699msec&lt;/code&gt;&lt;/p&gt;&#xA;&lt;h1 id=&#34;summary&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Summary&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;So I don&amp;rsquo;t fully understand these numbers yet&amp;hellip; 80-100 MiB/s isn&amp;rsquo;t super fast&#xA;and that&amp;rsquo;s across a parallelized workload&amp;hellip; The single threaded workloads have&#xA;awful performance so this tells me something is wrong&amp;hellip; I have a few ideas&amp;hellip;&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;ZFS dataset config options such as &lt;code&gt;ashift&lt;/code&gt; or the blocksize might be way misconfigured&lt;/li&gt;&#xA;&lt;li&gt;The disks/pool which came from a TrueNAS/FreeBSD machine may have some artifacts that I need to clean up&lt;/li&gt;&#xA;&lt;li&gt;The SAS controller I am using, which I flashed with IT firmware to get it into JBOD mode might be messed up&lt;/li&gt;&#xA;&lt;li&gt;The data cables themselves could be a problem&amp;hellip;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Points 3 and 4 are less likely given that the write speed does increase in the parallelized job but I&amp;rsquo;m a newbie so it&amp;rsquo;s time to dive in!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Playing with mdformat</title>
    <id>https://pype.dev/playing-with-mdformat/</id>
    <updated>2022-08-23T06:56:15Z</updated>
    <published>2022-08-23T06:56:15Z</published>
    <link href="https://pype.dev/playing-with-mdformat/" rel="alternate" type="text/html"></link>
    <content type="html">&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;what is taking so long black!!&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Paperless-NGX filtering on IDs instead of values</title>
    <id>https://pype.dev/paperless-ngx-filtering-on-ids-instead-of-values/</id>
    <updated>2022-08-09T08:28:51Z</updated>
    <published>2022-08-09T08:28:51Z</published>
    <link href="https://pype.dev/paperless-ngx-filtering-on-ids-instead-of-values/" rel="alternate" type="text/html"></link>
    <summary type="text">To filter for saved views from the admin console you have to use the of the tag you are using to filter on...</summary>
    <content type="html">&lt;p&gt;To filter for saved views from the admin console you have to use the &lt;code&gt;id&lt;/code&gt; of&#xA;the tag you are using to filter on&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;Ex: filtering for tags &amp;ldquo;Inbox&amp;rdquo; doesn&amp;rsquo;t work, but for tag 18 does (the id fo the&#xA;Inbox tag). I can find that ID by clicking on the tag and looking at the url&#xA;bar&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Mounting exFAT USB in Linux</title>
    <id>https://pype.dev/mounting-exfat-usb-in-linux/</id>
    <updated>2022-07-31T07:38:43Z</updated>
    <published>2022-07-31T07:38:43Z</published>
    <link href="https://pype.dev/mounting-exfat-usb-in-linux/" rel="alternate" type="text/html"></link>
    <content type="html">&lt;h1 id=&#34;steps&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Steps&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;&lt;code&gt;sudo fdisk -l&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;then look for the device and partition&lt;/p&gt;&#xA;&lt;p&gt;get the Type column&lt;/p&gt;&#xA;&lt;p&gt;mount&lt;/p&gt;&#xA;&lt;h2 id=&#34;example&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Example&lt;/span&gt; &lt;a href=&#34;#example&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;pre&gt;&lt;code&gt;&#xA;dumbledore in /media  NO PYTHON VENV SET &#xA;❯ sudo fdisk -l&#xA;&#xA;...&#xA;&#xA;Device     Boot    Start      End  Sectors  Size Id Type&#xA;/dev/sdk1  *        2048 60371951 60369904 28.8G  7 HPFS/NTFS/exFAT&#xA;/dev/sdk2       60371952 60437487    65536   32M ef EFI (FAT-12/16/32)&#xA;&#xA;&#xA;dumbledore in /media  NO PYTHON VENV SET &#xA;❯ sudo mount -t ntfs /dev/sdk1 /media/ventoy-usb -o uid=1000                       &#xA;NTFS signature is missing.&#xA;Failed to mount &#39;/dev/sdk1&#39;: Invalid argument&#xA;The device &#39;/dev/sdk1&#39; doesn&#39;t seem to have a valid NTFS.&#xA;Maybe the wrong device is used? Or the whole disk instead of a&#xA;partition (e.g. /dev/sda, not /dev/sda1)? Or the other way around?&#xA;&#xA;dumbledore in /media  NO PYTHON VENV SET &#xA;✗ sudo mount -t exfat /dev/sdk1 /media/ventoy-usb -o uid=1000&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Xrdp-Authentication-Required-To-Create-Managed-Color-Device</title>
    <id>https://pype.dev/xrdp-authentication-required-to-create-managed-color-device/</id>
    <updated>2022-07-18T00:00:00Z</updated>
    <published>2022-07-18T00:00:00Z</published>
    <link href="https://pype.dev/xrdp-authentication-required-to-create-managed-color-device/" rel="alternate" type="text/html"></link>
    <summary type="text">I just need to RDP into an Ubuntu box via Remmina and everytime I login I have to authenticate to create a color managed device... which I don&#39;t even know...</summary>
    <content type="html">&lt;p&gt;I just need to RDP into an Ubuntu box via Remmina and everytime I login I have&#xA;to authenticate to create a color managed device&amp;hellip; which I don&amp;rsquo;t even know&#xA;what that is!&lt;/p&gt;&#xA;&lt;p&gt;To fix it?&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;vim /etc/polkit-1/localauthority.conf.d/02-allow-colord.conf&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;polkit.addRule(function(action, subject) {&#xA; if ((action.id == &amp;quot;org.freedesktop.color-manager.create-device&amp;quot; ||&#xA; action.id == &amp;quot;org.freedesktop.color-manager.create-profile&amp;quot; ||&#xA; action.id == &amp;quot;org.freedesktop.color-manager.delete-device&amp;quot; ||&#xA; action.id == &amp;quot;org.freedesktop.color-manager.delete-profile&amp;quot; ||&#xA; action.id == &amp;quot;org.freedesktop.color-manager.modify-device&amp;quot; ||&#xA; action.id == &amp;quot;org.freedesktop.color-manager.modify-profile&amp;quot;) &amp;amp;&amp;amp;&#xA; subject.isInGroup(&amp;quot;{users}&amp;quot;)) {&#xA; return polkit.Result.YES;&#xA; }&#xA; });&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Give&amp;rsquo;r the &lt;code&gt;:x&lt;/code&gt;, logout, and you&amp;rsquo;re good to go&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Setup KVM to boot from local PXE server</title>
    <id>https://pype.dev/setup-kvm-to-boot-from-local-pxe-server/</id>
    <updated>2022-07-06T12:30:50Z</updated>
    <published>2022-07-06T12:30:50Z</published>
    <link href="https://pype.dev/setup-kvm-to-boot-from-local-pxe-server/" rel="alternate" type="text/html"></link>
    <summary type="text">Assuming you have a PXE server running you only need small edits to the virt-manager config</summary>
    <content type="html">&lt;p&gt;Assuming you have a PXE server running you only need small edits to the virt-manager config&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Self-hosted Docker registry with proxy pull through</title>
    <id>https://pype.dev/self-hosted-docker-registry-with-proxy-pull-through/</id>
    <updated>2022-07-06T06:44:35Z</updated>
    <published>2022-07-06T06:44:35Z</published>
    <link href="https://pype.dev/self-hosted-docker-registry-with-proxy-pull-through/" rel="alternate" type="text/html"></link>
    <summary type="text">I decided that I want to self-host all my docker images for the purposes of regularly rebuilding and security scanning. The first step is to set up a...</summary>
    <content type="html">&lt;p&gt;I decided that I want to self-host all my docker images for the purposes of&#xA;regularly rebuilding and security scanning. The first step is to set up a&#xA;registry, which coincidently enough you can do with a Docker container 😛!&lt;/p&gt;&#xA;&lt;p&gt;Instructions for setting up the proxy are on the offidical docker docs &lt;a href=&#34;https://docs.docker.com/registry/recipes/mirror/&#34;&gt;here&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h1 id=&#34;deployment&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Deployment&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;I chose to deploy with Portainer because I already use it for monitoring all my&#xA;docker containers. I deploy most container with Ansible but use Portainer to&#xA;setup a few more adhoc or non-git driven applications.&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>kvm-network-interface-via-nat-ubuntu-20</title>
    <id>https://pype.dev/kvm-network-interface-via-nat-ubuntu-20/</id>
    <updated>2022-06-25T07:20:41Z</updated>
    <published>2022-06-25T07:20:41Z</published>
    <link href="https://pype.dev/kvm-network-interface-via-nat-ubuntu-20/" rel="alternate" type="text/html"></link>
    <summary type="text">I have started using VMs more and more in my development workflow and it&#39;s impossible to work in a VM without an internet connection for me most of the time....</summary>
    <content type="html">&lt;p&gt;I have started using VMs more and more in my development workflow and it&amp;rsquo;s&#xA;impossible to work in a VM without an internet connection for me most of the&#xA;time. Setting up the KVM networking is kind of confusing to me and I&amp;rsquo;ve done it&#xA;two different ways. Here is how I set it up on my home desktop using NAT.&lt;/p&gt;&#xA;&lt;h1 id=&#34;credit&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Credit&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;First thing&amp;rsquo;s first: &lt;a href=&#34;https://computingforgeeks.com/managing-kvm-network-interfaces-in-linux/&#34;&gt;credit to this post&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h1 id=&#34;commands&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Commands&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;There was a &lt;code&gt;default&lt;/code&gt; network already made by virt-manager but my VM couldn&amp;rsquo;t connect over it at all&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;These commands got me up and running without even turning the VM off&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;I went full on &lt;code&gt;sudo -i&lt;/code&gt; for this just to make it easier - be careful&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h2 id=&#34;dump-an-existint-network-config&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Dump an existint network config&lt;/span&gt; &lt;a href=&#34;#dump-an-existint-network-config&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# as root&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;virsh net-dumpxml default &amp;gt; br1.xml&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;vim br1.xml&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;edit-it&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Edit it&lt;/span&gt; &lt;a href=&#34;#edit-it&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I was unsure what the ip range should be so I just stuck with the original blog.&#xA;The &lt;code&gt;default&lt;/code&gt; network had the CIDR block defined as &lt;code&gt;192.168.122.0/24&lt;/code&gt; which is different from my home network so I guess it&amp;rsquo;s fine?&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;network&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;name&amp;gt;&lt;/span&gt;br1&lt;span class=&#34;nt&#34;&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;forward&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;mode=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;nat&amp;#39;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;nat&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;lt;port&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;start=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;1024&amp;#39;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;end=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;65535&amp;#39;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;/nat&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;/forward&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;bridge&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;br1&amp;#39;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;stp=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;on&amp;#39;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;delay=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;ip&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;address=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;192.168.10.1&amp;#39;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;netmask=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;255.255.255.0&amp;#39;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;dhcp&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;lt;range&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;start=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;192.168.10.10&amp;#39;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;end=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;192.168.10.100&amp;#39;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;/&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;/dhcp&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;/ip&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;/network&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;define-a-network&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Define a network&lt;/span&gt; &lt;a href=&#34;#define-a-network&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;virsh net-define br1.xml&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;virsh net-autostart br1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then to check&amp;hellip;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;virsh net-list --all&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; Name      State    Autostart   Persistent&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;--------------------------------------------&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; br1       active   yes         yes&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; default   active   yes         yes&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;uuid&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;UUID&lt;/span&gt; &lt;a href=&#34;#uuid&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;&lt;code&gt;virsh net-uuid br1&lt;/code&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;magic&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Magic&lt;/span&gt; &lt;a href=&#34;#magic&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;&lt;code&gt;virsh attach-interface --domain &amp;lt;NAME OF VM&amp;gt; --type bridge --source br1 --model virtio --config --live&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;My VM, &lt;code&gt;ubuntu20.04&lt;/code&gt; was running and immediately connected to the newly attached device!&lt;/p&gt;&#xA;&lt;h1 id=&#34;credit-again&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Credit again&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;Visit the original post for more details - this serves more as as a quicker set of notes for future me&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>cheat on your man</title>
    <id>https://pype.dev/cheat-on-your-man/</id>
    <updated>2022-06-23T09:35:31Z</updated>
    <published>2022-06-23T09:35:31Z</published>
    <link href="https://pype.dev/cheat-on-your-man/" rel="alternate" type="text/html"></link>
    <summary type="text">can be a pain to read... and there&#39;s lots of alternatives out there and one I&#39;ve just started playing with is cheat</summary>
    <content type="html">&lt;p&gt;&lt;code&gt;man&lt;/code&gt; can be a pain to read&amp;hellip; and there&amp;rsquo;s lots of alternatives out there and one I&amp;rsquo;ve just started playing with is &lt;a href=&#34;https://github.com/cheat/cheat&#34;&gt;cheat&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;man man&lt;/code&gt; will give you this plus a billion more lines of docs, which is useful when you need it&amp;hellip;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;MAN&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;1&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;                                                                                                                       Manual pager utils                                                                                                                      MAN&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;1&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;NAME&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       man - an interface to the on-line reference manuals&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;SYNOPSIS&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       man  &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-C  file&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-d&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-D&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;--warnings&lt;span class=&#34;o&#34;&gt;[=&lt;/span&gt;warnings&lt;span class=&#34;o&#34;&gt;]]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-R encoding&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-L locale&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-m system&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;,...&lt;span class=&#34;o&#34;&gt;]]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-M path&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-S list&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-e extension&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-i&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;-I&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;--regex&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;--wildcard&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;--names-only&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-a&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-u&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;--no-subpages&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-P pager&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-r prompt&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-7&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-E encoding&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;--no-hyphenation&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;--no-justification&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-p string&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-t&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-T&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;device&lt;span class=&#34;o&#34;&gt;]]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-H&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;browser&lt;span class=&#34;o&#34;&gt;]]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-X&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;dpi&lt;span class=&#34;o&#34;&gt;]]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-Z&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[[&lt;/span&gt;section&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; page&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;.section&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; ...&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; ...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       man -k &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;apropos options&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; regexp ...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       man -K &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-w&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;-W&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-S list&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-i&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;-I&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;--regex&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;section&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; term ...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       man -f &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;whatis options&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; page ...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       man -l &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-C file&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-d&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-D&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;--warnings&lt;span class=&#34;o&#34;&gt;[=&lt;/span&gt;warnings&lt;span class=&#34;o&#34;&gt;]]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-R encoding&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-L locale&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-P pager&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-r prompt&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-7&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-E encoding&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-p string&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-t&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-T&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;device&lt;span class=&#34;o&#34;&gt;]]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-H&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;browser&lt;span class=&#34;o&#34;&gt;]]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-X&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;dpi&lt;span class=&#34;o&#34;&gt;]]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-Z&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; file ...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       man -w&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;-W &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-C file&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-d&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-D&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; page ...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       man -c &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-C file&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-d&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-D&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; page ...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       man &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-?V&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;DESCRIPTION&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       man is the system&lt;span class=&#34;err&#34;&gt;&amp;#39;&lt;/span&gt;s manual pager.  Each page argument given to man is normally the name of a program, utility or &lt;span class=&#34;k&#34;&gt;function&lt;/span&gt;.  The manual page associated with each of these arguments is &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt; found and displayed.  A section, &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; provided, will direct  man  to  look&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       only  in  that  section of the manual.  The default action is to search in all of the available sections following a pre-defined order &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;1 n l 8 3 2 3posix 3pm 3perl 3am 5 4 9 6 7&amp;#34;&lt;/span&gt; by default, unless overridden by the SECTION directive in /etc/manpath.config&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       and to show only the first page found, even &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; page exists in several sections.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       The table below shows the section numbers of the manual followed by the types of pages they contain.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;   Executable programs or shell commands&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;   System calls &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;functions provided by the kernel&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;   Library calls &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;functions within program libraries&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       &lt;span class=&#34;m&#34;&gt;4&lt;/span&gt;   Special files &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;usually found in /dev&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       &lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;   File formats and conventions eg /etc/passwd&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       &lt;span class=&#34;m&#34;&gt;6&lt;/span&gt;   Games&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       &lt;span class=&#34;m&#34;&gt;7&lt;/span&gt;   Miscellaneous &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;including macro packages and conventions&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;, e.g. man&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;7&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;, groff&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;7&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       &lt;span class=&#34;m&#34;&gt;8&lt;/span&gt;   System administration commands &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;usually only &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; root&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       &lt;span class=&#34;m&#34;&gt;9&lt;/span&gt;   Kernel routines &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;Non standard&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       A manual page consists of several sections.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       Conventional section names include NAME, SYNOPSIS, CONFIGURATION, DESCRIPTION, OPTIONS, EXIT STATUS, RETURN VALUE, ERRORS, ENVIRONMENT, FILES, VERSIONS, CONFORMING TO, NOTES, BUGS, EXAMPLE, AUTHORS, and SEE ALSO.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       The following conventions apply to the SYNOPSIS section and can be used as a guide in other sections.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       bold text          &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt; exactly as shown.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       italic text        replace with appropriate argument.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;-abc&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;             any or all arguments within &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; are optional.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       -a&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;-b              options delimited by &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; cannot be used together.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       argument ...       argument is repeatable.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;expression&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; ...   entire expression within &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; is repeatable.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       Exact rendering may vary depending on the output device.  For instance, man will usually not be able to render italics when running in a terminal, and will typically use underlined or coloured text instead.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       The &lt;span class=&#34;nb&#34;&gt;command&lt;/span&gt; or &lt;span class=&#34;k&#34;&gt;function&lt;/span&gt; illustration is a pattern that should match all possible invocations.  In some cases it is advisable to illustrate several exclusive invocations as is shown in the SYNOPSIS section of this manual page.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;EXAMPLES&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       man ls&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           Display the manual page &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; the item &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;program&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; ls.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       man man.7&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           Display the manual page &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; macro package man from section 7.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;but-what-if-you-don-t&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;But what if you don’t?&lt;/span&gt; &lt;a href=&#34;#but-what-if-you-don-t&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;&lt;code&gt;cheat man&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# To convert a man page to pdf:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;man -t bash &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; ps2pdf - bash.pdf&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# To view the ascii chart:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;man &lt;span class=&#34;m&#34;&gt;7&lt;/span&gt; ascii&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You get tiny examples to remind you of what you &lt;strong&gt;probably&lt;/strong&gt; are trying to do!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Add colored indicators to your dataframes html representation</title>
    <id>https://pype.dev/add-colored-indicators-to-your-dataframes-html-representation/</id>
    <updated>2022-06-04T06:12:33Z</updated>
    <published>2022-06-04T06:12:33Z</published>
    <link href="https://pype.dev/add-colored-indicators-to-your-dataframes-html-representation/" rel="alternate" type="text/html"></link>
    <summary type="text">Mike Driscoll recently tweeted about making colored out with pandas DataFrames and I just had to try it for myself</summary>
    <content type="html">&lt;p&gt;&lt;a href=&#34;https://twitter.com/driscollis&#34;&gt;Mike Driscoll&lt;/a&gt; recently tweeted about making&#xA;colored out with pandas DataFrames and I just had to try it for myself&lt;/p&gt;&#xA;&lt;h1 id=&#34;use-case&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Use Case&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;First though&amp;hellip; why?&#xA;My biggest use case is a monitoring pipeline of mine&amp;hellip; The details aside, the&#xA;output of my pipeline is a dataframe where each row has information about a&#xA;failed pipeline that I need to go look into. I dump that result to a simle html&#xA;file that&amp;rsquo;s hosted on an internal site and the file is updated every couple of&#xA;hours. Adding some colored indicators automatically to the rows to help me&#xA;assess severity of each record would be a handy way to quickly get an&#xA;understanding the state of our pipelines.&lt;/p&gt;&#xA;&lt;h1 id=&#34;how&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;How?&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;The docs for the &lt;code&gt;applymap&lt;/code&gt; method state simply:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;Apply a CSS-styling function elementwise.&#xA;&#xA;Updates the HTML representation with the result.&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;So we can write a function that returns &lt;code&gt;color: {color}&lt;/code&gt; based on the dataframe&#xA;values and when we drop that dataframe to html we&amp;rsquo;ll have some simple css&#xA;styling applied automagically!&lt;/p&gt;&#xA;&lt;p&gt;By default the function will be applied to all columns of the dataframe, but&#xA;that&amp;rsquo;s not useful if the columns are different types which is usually the case.&#xA;Luckily there is a &lt;code&gt;subset&lt;/code&gt; keyword to only apply to the columns you need!&lt;/p&gt;&#xA;&lt;p&gt;Consider my example&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read_csv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;cars.csv&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;mpg_color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;     &lt;span class=&#34;n&#34;&gt;color&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;red&amp;#34;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;val&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;21&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;green&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;     &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;color: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;style&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;applymap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mpg_color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;subset&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;mpg&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;to_html&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;color.html&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I want to quickly see if the &lt;code&gt;mpg&lt;/code&gt; is any good for the cars in the cars dataset&#xA;and I&amp;rsquo;ll define &amp;ldquo;good&amp;rdquo; as better than 21 mpg (not great I know but just for the&#xA;sake of discussion&amp;hellip;)&lt;/p&gt;&#xA;&lt;p&gt;The function returns an appropriate css string and after I &lt;code&gt;style.applymap&lt;/code&gt; on just the &lt;code&gt;mpg&lt;/code&gt; column we get this!&lt;/p&gt;&#xA;&lt;style type=&#34;text/css&#34;&gt;&#xA;#T_95e99_row0_col1, #T_95e99_row1_col1, #T_95e99_row2_col1, #T_95e99_row3_col1 {&#xA;  color: green;&#xA;}&#xA;#T_95e99_row4_col1 {&#xA;  color: red;&#xA;}&#xA;&lt;/style&gt;&#xA;&lt;table id=&#34;T_95e99&#34;&gt;&#xA;  &lt;thead&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th class=&#34;blank level0&#34; &gt;&amp;nbsp;&lt;/th&gt;&#xA;      &lt;th id=&#34;T_95e99_level0_col0&#34; class=&#34;col_heading level0 col0&#34; &gt;Unnamed: 0&lt;/th&gt;&#xA;      &lt;th id=&#34;T_95e99_level0_col1&#34; class=&#34;col_heading level0 col1&#34; &gt;mpg&lt;/th&gt;&#xA;      &lt;th id=&#34;T_95e99_level0_col2&#34; class=&#34;col_heading level0 col2&#34; &gt;cyl&lt;/th&gt;&#xA;      &lt;th id=&#34;T_95e99_level0_col3&#34; class=&#34;col_heading level0 col3&#34; &gt;disp&lt;/th&gt;&#xA;      &lt;th id=&#34;T_95e99_level0_col4&#34; class=&#34;col_heading level0 col4&#34; &gt;hp&lt;/th&gt;&#xA;      &lt;th id=&#34;T_95e99_level0_col5&#34; class=&#34;col_heading level0 col5&#34; &gt;drat&lt;/th&gt;&#xA;      &lt;th id=&#34;T_95e99_level0_col6&#34; class=&#34;col_heading level0 col6&#34; &gt;wt&lt;/th&gt;&#xA;      &lt;th id=&#34;T_95e99_level0_col7&#34; class=&#34;col_heading level0 col7&#34; &gt;qsec&lt;/th&gt;&#xA;      &lt;th id=&#34;T_95e99_level0_col8&#34; class=&#34;col_heading level0 col8&#34; &gt;vs&lt;/th&gt;&#xA;      &lt;th id=&#34;T_95e99_level0_col9&#34; class=&#34;col_heading level0 col9&#34; &gt;am&lt;/th&gt;&#xA;      &lt;th id=&#34;T_95e99_level0_col10&#34; class=&#34;col_heading level0 col10&#34; &gt;gear&lt;/th&gt;&#xA;      &lt;th id=&#34;T_95e99_level0_col11&#34; class=&#34;col_heading level0 col11&#34; &gt;carb&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th id=&#34;T_95e99_level0_row0&#34; class=&#34;row_heading level0 row0&#34; &gt;0&lt;/th&gt;&#xA;      &lt;td id=&#34;T_95e99_row0_col0&#34; class=&#34;data row0 col0&#34; &gt;Mazda RX4&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row0_col1&#34; class=&#34;data row0 col1&#34; &gt;21.000000&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row0_col2&#34; class=&#34;data row0 col2&#34; &gt;6&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row0_col3&#34; class=&#34;data row0 col3&#34; &gt;160.000000&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row0_col4&#34; class=&#34;data row0 col4&#34; &gt;110&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row0_col5&#34; class=&#34;data row0 col5&#34; &gt;3.900000&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row0_col6&#34; class=&#34;data row0 col6&#34; &gt;2.620000&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row0_col7&#34; class=&#34;data row0 col7&#34; &gt;16.460000&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row0_col8&#34; class=&#34;data row0 col8&#34; &gt;0&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row0_col9&#34; class=&#34;data row0 col9&#34; &gt;1&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row0_col10&#34; class=&#34;data row0 col10&#34; &gt;4&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row0_col11&#34; class=&#34;data row0 col11&#34; &gt;4&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th id=&#34;T_95e99_level0_row1&#34; class=&#34;row_heading level0 row1&#34; &gt;1&lt;/th&gt;&#xA;      &lt;td id=&#34;T_95e99_row1_col0&#34; class=&#34;data row1 col0&#34; &gt;Mazda RX4 Wag&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row1_col1&#34; class=&#34;data row1 col1&#34; &gt;21.000000&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row1_col2&#34; class=&#34;data row1 col2&#34; &gt;6&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row1_col3&#34; class=&#34;data row1 col3&#34; &gt;160.000000&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row1_col4&#34; class=&#34;data row1 col4&#34; &gt;110&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row1_col5&#34; class=&#34;data row1 col5&#34; &gt;3.900000&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row1_col6&#34; class=&#34;data row1 col6&#34; &gt;2.875000&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row1_col7&#34; class=&#34;data row1 col7&#34; &gt;17.020000&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row1_col8&#34; class=&#34;data row1 col8&#34; &gt;0&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row1_col9&#34; class=&#34;data row1 col9&#34; &gt;1&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row1_col10&#34; class=&#34;data row1 col10&#34; &gt;4&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row1_col11&#34; class=&#34;data row1 col11&#34; &gt;4&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th id=&#34;T_95e99_level0_row2&#34; class=&#34;row_heading level0 row2&#34; &gt;2&lt;/th&gt;&#xA;      &lt;td id=&#34;T_95e99_row2_col0&#34; class=&#34;data row2 col0&#34; &gt;Datsun 710&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row2_col1&#34; class=&#34;data row2 col1&#34; &gt;22.800000&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row2_col2&#34; class=&#34;data row2 col2&#34; &gt;4&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row2_col3&#34; class=&#34;data row2 col3&#34; &gt;108.000000&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row2_col4&#34; class=&#34;data row2 col4&#34; &gt;93&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row2_col5&#34; class=&#34;data row2 col5&#34; &gt;3.850000&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row2_col6&#34; class=&#34;data row2 col6&#34; &gt;2.320000&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row2_col7&#34; class=&#34;data row2 col7&#34; &gt;18.610000&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row2_col8&#34; class=&#34;data row2 col8&#34; &gt;1&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row2_col9&#34; class=&#34;data row2 col9&#34; &gt;1&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row2_col10&#34; class=&#34;data row2 col10&#34; &gt;4&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row2_col11&#34; class=&#34;data row2 col11&#34; &gt;1&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th id=&#34;T_95e99_level0_row3&#34; class=&#34;row_heading level0 row3&#34; &gt;3&lt;/th&gt;&#xA;      &lt;td id=&#34;T_95e99_row3_col0&#34; class=&#34;data row3 col0&#34; &gt;Hornet 4 Drive&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row3_col1&#34; class=&#34;data row3 col1&#34; &gt;21.400000&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row3_col2&#34; class=&#34;data row3 col2&#34; &gt;6&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row3_col3&#34; class=&#34;data row3 col3&#34; &gt;258.000000&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row3_col4&#34; class=&#34;data row3 col4&#34; &gt;110&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row3_col5&#34; class=&#34;data row3 col5&#34; &gt;3.080000&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row3_col6&#34; class=&#34;data row3 col6&#34; &gt;3.215000&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row3_col7&#34; class=&#34;data row3 col7&#34; &gt;19.440000&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row3_col8&#34; class=&#34;data row3 col8&#34; &gt;1&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row3_col9&#34; class=&#34;data row3 col9&#34; &gt;0&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row3_col10&#34; class=&#34;data row3 col10&#34; &gt;3&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row3_col11&#34; class=&#34;data row3 col11&#34; &gt;1&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th id=&#34;T_95e99_level0_row4&#34; class=&#34;row_heading level0 row4&#34; &gt;4&lt;/th&gt;&#xA;      &lt;td id=&#34;T_95e99_row4_col0&#34; class=&#34;data row4 col0&#34; &gt;Hornet Sportabout&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row4_col1&#34; class=&#34;data row4 col1&#34; &gt;18.700000&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row4_col2&#34; class=&#34;data row4 col2&#34; &gt;8&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row4_col3&#34; class=&#34;data row4 col3&#34; &gt;360.000000&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row4_col4&#34; class=&#34;data row4 col4&#34; &gt;175&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row4_col5&#34; class=&#34;data row4 col5&#34; &gt;3.150000&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row4_col6&#34; class=&#34;data row4 col6&#34; &gt;3.440000&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row4_col7&#34; class=&#34;data row4 col7&#34; &gt;17.020000&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row4_col8&#34; class=&#34;data row4 col8&#34; &gt;0&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row4_col9&#34; class=&#34;data row4 col9&#34; &gt;0&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row4_col10&#34; class=&#34;data row4 col10&#34; &gt;3&lt;/td&gt;&#xA;      &lt;td id=&#34;T_95e99_row4_col11&#34; class=&#34;data row4 col11&#34; &gt;2&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Samba on Ubuntu 22 needs “inherit permissions” set</title>
    <id>https://pype.dev/samba-on-ubuntu-22-needs-inherit-permissions-set/</id>
    <updated>2022-05-31T06:30:42Z</updated>
    <published>2022-05-31T06:30:42Z</published>
    <link href="https://pype.dev/samba-on-ubuntu-22-needs-inherit-permissions-set/" rel="alternate" type="text/html"></link>
    <summary type="text">see samba config on hogwarts</summary>
    <content type="html">&lt;p&gt;see samba config on hogwarts&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Filtering emails with core utils</title>
    <id>https://pype.dev/filtering-emails-with-core-utils/</id>
    <updated>2022-05-30T06:09:27Z</updated>
    <published>2022-05-30T06:09:27Z</published>
    <link href="https://pype.dev/filtering-emails-with-core-utils/" rel="alternate" type="text/html"></link>
    <content type="html">&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;email1@me.com&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;somebody_else@gmail.com&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#! /bin/bash&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# pick multiple emails from list and combine into comma seperated array&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;emails&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;cat .../emails &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; fzf -m &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; sed &lt;span class=&#34;s1&#34;&gt;&amp;#39;s/^\|$/&amp;#34;/g&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;paste -sd,&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$emails&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Reindex Nextcloud After Adding Data via CLI</title>
    <id>https://pype.dev/reindex-nextcloud-after-adding-data-via-cli/</id>
    <updated>2022-05-29T15:34:33Z</updated>
    <published>2022-05-29T15:34:33Z</published>
    <link href="https://pype.dev/reindex-nextcloud-after-adding-data-via-cli/" rel="alternate" type="text/html"></link>
    <summary type="text">I wrote here about setting up as the owner of any directories you want nextcloud to manage. However, I regularly struggle wtih permissions issues on my NAS...</summary>
    <content type="html">&lt;h1 id=&#34;my-nextcloud-woes&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;My Nextcloud woes&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;I wrote &lt;a href=&#34;%22nextcloud-permissions-with-zfs-and-ansible-nas%22&#34;&gt;here&lt;/a&gt; about setting&#xA;up &lt;code&gt;www-data&lt;/code&gt; as the owner of any directories you want nextcloud to manage.&#xA;However, I regularly struggle wtih permissions issues on my NAS because of the&#xA;external storage app anyways so I&amp;rsquo;ve decided to just put our photos in the spot&#xA;Nextcloud would otherwise put them, and use this as healthy pressure on our&#xA;family to organize our photos and put the ones we care about with the rest of&#xA;our family media.&lt;/p&gt;&#xA;&lt;h1 id=&#34;migration&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Migration&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;Because I had a ton of photos on the NAS anyways that I wanted moved over to&#xA;Nextcloud I just rsync&amp;rsquo;d the photos directory on my NAS to the user&amp;rsquo;s photos&#xA;directory in nextcloud but they weren&amp;rsquo;t showing up in the web UI!&lt;/p&gt;&#xA;&lt;h1 id=&#34;the-fix&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Fix?&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;As www-data I needed to &lt;code&gt;php /var/www/nextcloud/occ files:scan --all&lt;/code&gt; inside my&#xA;nextcloud docker container AFTER moving a bunch of photos off my &amp;ldquo;NAS&amp;rdquo; into the&#xA;folder mounted to the nextcloud container as its data folder! Before I did this&#xA;they weren&amp;rsquo;t showing up in the web UI/&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>arr client config</title>
    <id>https://pype.dev/arr-download-client-config/</id>
    <updated>2022-05-28T13:29:28Z</updated>
    <published>2022-05-28T13:29:28Z</published>
    <link href="https://pype.dev/arr-download-client-config/" rel="alternate" type="text/html"></link>
    <summary type="text">TIL that when setting up download clients for radarr/sonarr/lidarr/readarr/bazarr/prowlarr that you can utilize internal DNS and instead of hardcoding an IP...</summary>
    <content type="html">&lt;p&gt;TIL that when setting up download clients for&#xA;radarr/sonarr/lidarr/readarr/bazarr/prowlarr that you can utilize internal DNS&#xA;and instead of hardcoding an IP address of your download client server, can use&#xA;just the CNAME record (ie. instead of 172.10.14.13 I can use&#xA;transmission.mydomain.com&amp;hellip; notice the lact of http(s)://&amp;hellip; adding that won&amp;rsquo;t&#xA;allow the connection to work/&lt;/p&gt;&#xA;&lt;p&gt;Furthermore, you can use internal DNS to lookup the domain, not the subdomain,&#xA;and expose the port, like &lt;code&gt;mydomain.com:7878&lt;/code&gt; for sonarr. This was simpler to&#xA;maintain because I don&amp;rsquo;t change which ports an application exposes or utilizes&#xA;hardly ever, plus I don&amp;rsquo;t need to maintain CNAME records for every service!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Add space to your LVM on Ubuntu</title>
    <id>https://pype.dev/add-space-to-your-lvm-on-ubuntu/</id>
    <updated>2022-05-26T21:33:55Z</updated>
    <published>2022-05-26T21:33:55Z</published>
    <link href="https://pype.dev/add-space-to-your-lvm-on-ubuntu/" rel="alternate" type="text/html"></link>
    <summary type="text">I ran out of space on the SSD in my server when doing some file transfers but only 100GB was used of a 256 GB SSD?</summary>
    <content type="html">&lt;p&gt;I ran out of space on the SSD in my server when doing some file transfers but only 100GB was used of a 256 GB SSD?&lt;/p&gt;&#xA;&lt;h1 id=&#34;lvm&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;LVM&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;When installing Ubuntu live server the default option for how to partition the&#xA;disk (in my experience) has been to setup an LVM group that defaults to less&#xA;than the available space. Most recently I put Ubuntu server on a 256 GB SSD but&#xA;the main partition was formatted as an LVM group with 100GB of storage&amp;hellip; I&#xA;didn&amp;rsquo;t think anything of this even though I&amp;rsquo;m mostly used to EXT4.&lt;/p&gt;&#xA;&lt;p&gt;I think the reason for LVMs is performance, but in hindsight, I don&amp;rsquo;t really&#xA;care much about the performance differences, I really just want all my storage&#xA;that&amp;rsquo;s fast enough&lt;/p&gt;&#xA;&lt;h1 id=&#34;extending-the-lvm&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Extending the LVM&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;A moment of googling brought me to Ubuntu&amp;rsquo;s wiki and I&#xA;learned that I can expand my LVM to the space I need&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;sudo lvdisplay&lt;/code&gt; and &lt;code&gt;sudo pvdisplay&lt;/code&gt; show detailed views of the logical volumes and physical volumes respectively.&lt;/p&gt;&#xA;&lt;p&gt;Take a look at those and find the volume you need to extend. For me I found this:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  --- Logical volume ---&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  LV Path                /dev/ubuntu-vg/ubuntu-lv&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  LV Name                ubuntu-lv&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  VG Name                ubuntu-vg&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  LV Write Access        read/write&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  LV Status              available&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  ...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;There&amp;rsquo;s more that you&amp;rsquo;ll see but this is what&amp;rsquo;s relevant - I need to extend the&#xA;&lt;code&gt;ubuntu-lv&lt;/code&gt; logical volume in the &lt;code&gt;ubuntu-vg&lt;/code&gt; volume group.&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;sudo lvextend -L +50g ubuntu-vg/ubuntu-lv&lt;/code&gt; gives me 50 more GB of storage which should be enough for at least tonight 🤓&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://wiki.ubuntu.com/Lvm&#34;&gt;RTFM&lt;/a&gt;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Tdarr worker nodes share the cache!</title>
    <id>https://pype.dev/tdarr-worker-nodes-share-the-cache/</id>
    <updated>2022-05-25T06:36:59Z</updated>
    <published>2022-05-25T06:36:59Z</published>
    <link href="https://pype.dev/tdarr-worker-nodes-share-the-cache/" rel="alternate" type="text/html"></link>
    <summary type="text">When working with tdarr remote nodes, they need to have access not only to the same libraries but also the same transcode cache as the server otherwise the...</summary>
    <content type="html">&lt;p&gt;When working with tdarr remote nodes, they need to have access not only to the&#xA;same libraries but also the same transcode cache as the server otherwise the&#xA;transcodes will fail&amp;hellip;&lt;/p&gt;&#xA;&lt;h1 id=&#34;network-setup&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Network Setup&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;To explain I&amp;rsquo;ll give a brief overview of my home setup&lt;/p&gt;&#xA;&lt;p&gt;I have an old Dell PowerEdge R610 as my main server running a live server distribution of Ubuntu.&#xA;I use ZFS for my NAS file system, and most of my datasets are accesible over my home network.&#xA;I have a Tdarr server running in a docker container on the R610.&lt;/p&gt;&#xA;&lt;p&gt;In my office I dailyi drive a gaming desktop with an Nvidia 2060 Super running Ubuntu as well.&#xA;On that desktop I am running a Tdarr node in a docker container.&#xA;The container has access to the network folders with my media.&lt;/p&gt;&#xA;&lt;h1 id=&#34;initial-magic&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Initial Magic&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;When I spun up  a tdarr node on my desktop, the tdarr server running on my R610 automatically registered the node, which was freaking amazing.&#xA;That magic though spoiled me and I thought that I didn&amp;rsquo;t need to read the rest of the docs&amp;hellip;&lt;/p&gt;&#xA;&lt;h1 id=&#34;initial-fail&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Initial Fail&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;I setup a transcode cache directory on the R610 locally and a separate transcode cache on my desktop that the remote tdarr node would use.&#xA;Having them separated led to 2 main issues:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Transcodes were not being migrated back to my library properly&lt;/li&gt;&#xA;&lt;li&gt;I was running out of disk space on my desktop because tdarr wasn&amp;rsquo;t deleting the completed cache files properly.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h1 id=&#34;the-fix&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Fix&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;Make a transcode cache directory accessible on my network, and give access to that directory to the docker container running my remote tdarr node.&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Local DNS with Pi-hole</title>
    <id>https://pype.dev/local-dns-with-pi-hole/</id>
    <updated>2022-05-23T09:40:59Z</updated>
    <published>2022-05-23T09:40:59Z</published>
    <link href="https://pype.dev/local-dns-with-pi-hole/" rel="alternate" type="text/html"></link>
    <summary type="text">Tailscale is way easier than this... I was doing this local DNS overwrite in Pi-hole before running tailscale and I haven&#39;t just totally &#34;kicked the habit&#34;...</summary>
    <content type="html">&lt;h2 id=&#34;spoilers&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Spoilers&lt;/span&gt; &lt;a href=&#34;#spoilers&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Tailscale is way easier than this&amp;hellip; I was doing this local DNS overwrite in&#xA;Pi-hole before running tailscale and I haven&amp;rsquo;t just totally &amp;ldquo;kicked the habit&amp;rdquo;&#xA;yet, so for anyone NOT running tailcale, but wanting local HTTPS and using&#xA;Pi-Hole this method would work fine&lt;/p&gt;&#xA;&lt;h2 id=&#34;intro&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Intro&lt;/span&gt; &lt;a href=&#34;#intro&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I use &lt;a href=&#34;https://pi-hole.net/&#34;&gt;pihole&lt;/a&gt; as my DNS server at home. I run unbound as&#xA;well and have a pretty standard setup from their docs.&lt;/p&gt;&#xA;&lt;p&gt;Pi-hole does 2 primary things for me:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;dns sink-hold, the primary use case I believe&lt;/li&gt;&#xA;&lt;li&gt;local SSL for all my self-hosted apps&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;caveat&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Caveat&lt;/span&gt; &lt;a href=&#34;#caveat&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I know for sure there are better ways to do this, but there&amp;rsquo;s also worse&#xA;ones&amp;hellip; so for now this has been my pattern, and it&amp;rsquo;s only bitten me in the&#xA;butt when I&amp;rsquo;ve forgotten to add the final CNAME record&amp;hellip; which&amp;rsquo;ll make sense&#xA;in a sec.&lt;/p&gt;&#xA;&lt;h2 id=&#34;process&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Process&lt;/span&gt; &lt;a href=&#34;#process&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;It&amp;rsquo;s really quite simple - in pihole I have a DNS record for my domain pointing&#xA;to my primary server&lt;/p&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250706114501_8c34a31e.png&#34; alt=&#34;20250706114501_8c34a31e.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;Then for each service that I want to keep everything resolved locally for I add a CNAME&lt;/p&gt;&#xA;&lt;figure&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/20250706114557_916fb4c4.png&#34; alt=&#34;20250706114557_916fb4c4.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;With DNS resolving this way for clients using my pihole, the networking all&#xA;stays local and I still get HTTPS for my wildcard cert in cloudflare&lt;/p&gt;&#xA;&lt;h2 id=&#34;why&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Why?&lt;/span&gt; &lt;a href=&#34;#why&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;The reasons I do this are simple:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;I&amp;rsquo;ve been doing it since I started homelabbing and it started out of misunderstanding of how networking works &lt;em&gt;at all&lt;/em&gt;&lt;/li&gt;&#xA;&lt;li&gt;I use a home dashboard with https:// links, and it&amp;rsquo;s nice to just use that&#xA;same dashbaord publically or at home. With local DNS resolution then I can&#xA;whitelist some services, but conveniently access over the public url with https&#xA;but routing such that my whitelist let&amp;rsquo;s me in when it wouldn&amp;rsquo;t if I tried to&#xA;access the service from an external client&lt;/li&gt;&#xA;&lt;li&gt;it&amp;rsquo;s my homelab - I can do what I want&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;it-s-too-complicated&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;It’s too complicated&lt;/span&gt; &lt;a href=&#34;#it-s-too-complicated&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Honestly, as simple as this is, it is tedious and kind of complicated&amp;hellip;&#xA;There&amp;rsquo;s options to make it better&amp;hellip;&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;script any service deployment to update the pihole /etc/host file&lt;/li&gt;&#xA;&lt;li&gt;just use tailscale&amp;hellip;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Configure bridge network on Ubuntu 22.04 with Netplan</title>
    <id>https://pype.dev/configure-bridge-network-on-ubuntu-22-04-with-netplan/</id>
    <updated>2022-05-22T14:55:28Z</updated>
    <published>2022-05-22T14:55:28Z</published>
    <link href="https://pype.dev/configure-bridge-network-on-ubuntu-22-04-with-netplan/" rel="alternate" type="text/html"></link>
    <summary type="text">See 02-....yaml in ansible-nas</summary>
    <content type="html">&lt;p&gt;See 02-&amp;hellip;.yaml in ansible-nas&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Netplan change from Focal to Jammy</title>
    <id>https://pype.dev/netplan-change-from-focal-to-jammy/</id>
    <updated>2022-05-22T13:23:17Z</updated>
    <published>2022-05-22T13:23:17Z</published>
    <link href="https://pype.dev/netplan-change-from-focal-to-jammy/" rel="alternate" type="text/html"></link>
    <summary type="text">I am revamping my home server and bumped myself early up to Jammy Jellyfish... however to my peril I reused my netplan config and after hitting my server...</summary>
    <content type="html">&lt;p&gt;I am revamping my home server and bumped myself early up to Jammy Jellyfish&amp;hellip;&#xA;however to my peril I reused my netplan config and after hitting my server with&#xA;the &amp;lsquo;ol &lt;code&gt;netplan apply&lt;/code&gt; I lost connection&amp;hellip;&#xA;DNS still seemed to kinda work externally, but internally nothing was up&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;Turns out Netplan got a little change in how to express the &lt;code&gt;gateway&lt;/code&gt; key in the netplan config!&lt;/p&gt;&#xA;&lt;p&gt;Old Ubuntu 20.04 way&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;network&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;version&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;ethernets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;enp0s4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;addresses&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;192.168.1&lt;/span&gt;&lt;span class=&#34;l&#34;&gt;.{Static IP}/24]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;gateway4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;192.168.1.1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# &amp;lt;-- This changes!&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;nameservers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;addresses&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;192.168.1.1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1.1.1.1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;New jammin way for Jammy Jellyfish (&lt;strong&gt;at least that worked for me&lt;/strong&gt;)&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;network&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;version&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;ethernets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;enp0s4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;addresses&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;192.168.1&lt;/span&gt;&lt;span class=&#34;l&#34;&gt;.{Static IP}/24]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;routes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;to&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;default&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;via&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;192.168.1.1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;nameservers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;addresses&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;192.168.1.1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1.1.1.1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>How I use Nextcloud for safe central storage</title>
    <id>https://pype.dev/how-i-use-nextcloud-for-safe-central-storage/</id>
    <updated>2022-05-19T21:17:42Z</updated>
    <published>2022-05-19T21:17:42Z</published>
    <link href="https://pype.dev/how-i-use-nextcloud-for-safe-central-storage/" rel="alternate" type="text/html"></link>
    <summary type="text">Setup admin 2. External Storage extension 3. Add my nas zfs dataset 4. chown -R www-data:www-data on anything nextcloud uploads to.</summary>
    <content type="html">&lt;ol&gt;&#xA;&lt;li&gt;Setup admin&lt;/li&gt;&#xA;&lt;li&gt;External Storage extension&lt;/li&gt;&#xA;&lt;li&gt;Add my nas zfs dataset&lt;/li&gt;&#xA;&lt;li&gt;chown -R www-data:www-data on anything nextcloud uploads to.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Subset a list based on values in another list with itertools.compress</title>
    <id>https://pype.dev/subset-a-list-based-on-values-in-another-list-with-itertools-compress/</id>
    <updated>2022-05-19T14:22:58Z</updated>
    <published>2022-05-19T14:22:58Z</published>
    <link href="https://pype.dev/subset-a-list-based-on-values-in-another-list-with-itertools-compress/" rel="alternate" type="text/html"></link>
    <summary type="text">I have list [True, False, False, True] and another list [1, 2, 3, 4] and a use case where I want to filter list 2 based on list 1 to remove values that line...</summary>
    <content type="html">&lt;p&gt;I have list [True, False, False, True] and another list [1, 2, 3, 4] and a use&#xA;case where I want to filter list 2 based on list 1 to remove values that line&#xA;up with the element False in list 1&amp;hellip;. so the outcome will be [1, 4].&#xA;list(compress(list2, list1)) will do it. As long as you can create a mask for&#xA;the filter than itertool.compress will be your friend!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Nextcloud permissions with ZFS and Ansible-NAS</title>
    <id>https://pype.dev/nextcloud-permissions-with-zfs-and-ansible-nas/</id>
    <updated>2022-05-19T13:55:20Z</updated>
    <published>2022-05-19T13:55:20Z</published>
    <link href="https://pype.dev/nextcloud-permissions-with-zfs-and-ansible-nas/" rel="alternate" type="text/html"></link>
    <summary type="text">As the nextcloud docs say... if you want to write to an external volume that location has to be writeable by the user/group on the host system... so if that...</summary>
    <content type="html">&lt;h1 id=&#34;tl-dr&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;TL;DR&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;As the nextcloud docs say&amp;hellip; if you want to write to an external volume that&#xA;location has to be writeable by the user/group &lt;code&gt;www-data&lt;/code&gt; on the host system&amp;hellip;&#xA;so if that makes sense to you then this TIL probably isn&amp;rsquo;t a ton of value.. if&#xA;not however, read on :)&lt;/p&gt;&#xA;&lt;h1 id=&#34;case-study&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Case Study&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;You want to self-host your own cloud and use a smart file system for convenience&amp;hellip;&#xA;Nextcloud and ZFS are pretty common goto answers for each of those problems.&lt;/p&gt;&#xA;&lt;p&gt;My home NAS is built on ZFS and among other things I have a &lt;code&gt;zpool&lt;/code&gt; named&#xA;&lt;code&gt;tank&lt;/code&gt; and nested in there is a &lt;code&gt;tank/nas&lt;/code&gt; dataset with several child zfs&#xA;datasets under that.&lt;/p&gt;&#xA;&lt;p&gt;I want to use nextcloud mainly for auto-uploading photos from my wife&amp;rsquo;s and my phones for automatic backups.&#xA;The issue is that the nextcloud application (I run in Docker) is fixed as the&#xA;&lt;code&gt;www-data&lt;/code&gt; user and so any volume/folder that you want nextcloud to write to&#xA;needs to be permissioned such that &lt;code&gt;www-data&lt;/code&gt; owns it&amp;hellip; but I don&amp;rsquo;t want&#xA;&lt;code&gt;www-data&lt;/code&gt; to own everything in my NAS&amp;hellip; so what&amp;rsquo;s a girl to do?&lt;/p&gt;&#xA;&lt;h1 id=&#34;solution&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Solution&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;Well, one way to go is to just utilize docker volumes, write the data in the&#xA;container to &lt;code&gt;/var/www/html&lt;/code&gt; and let that be the place your data backsup to.&lt;/p&gt;&#xA;&lt;p&gt;I still wanted nextcloud to automatically write right to my NAS so I created a&#xA;&lt;code&gt;nextcloud-upload&lt;/code&gt; directory inside of &lt;code&gt;tank/nas/media/photos&lt;/code&gt; (photos cause&#xA;that&amp;rsquo;s all that gets automatically uploaded)&lt;/p&gt;&#xA;&lt;p&gt;Then I &lt;code&gt;chown -R www-data:www-data /tank/nas/media/photos/nextcloud-upload&lt;/code&gt; so&#xA;that just that sub-folder is owned by &lt;code&gt;www-data&lt;/code&gt;. Now everyone&amp;rsquo;s happy!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>See ZFS snapshot disk usage</title>
    <id>https://pype.dev/see-zfs-snapshot-disk-usage/</id>
    <updated>2022-05-19T06:05:23Z</updated>
    <published>2022-05-19T06:05:23Z</published>
    <link href="https://pype.dev/see-zfs-snapshot-disk-usage/" rel="alternate" type="text/html"></link>
    <summary type="text">As I was cleaning up my NAS recently I noticed that I ran out of storage even though my disk usage looked pretty low... turns out I was keeping a mega-ton of...</summary>
    <content type="html">&lt;p&gt;As I was cleaning up my NAS recently I noticed that I ran out of storage even&#xA;though my disk usage looked pretty low&amp;hellip; turns out I was keeping a mega-ton of&#xA;ZFS snapshots and due to my own ignorance at the time didn&amp;rsquo;t realize the&#xA;storage cost of this!&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;zfs list-o space tank/home&lt;/code&gt; will show the disk usage of the dataset and snapshots in &lt;code&gt;tank/home&lt;/code&gt;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Deleting files on remote storage from Ubuntu might not do what you think</title>
    <id>https://pype.dev/deleting-files-on-remote-storage-from-ubuntu-might-not-do-what-you-think/</id>
    <updated>2022-05-19T05:51:50Z</updated>
    <published>2022-05-19T05:51:50Z</published>
    <link href="https://pype.dev/deleting-files-on-remote-storage-from-ubuntu-might-not-do-what-you-think/" rel="alternate" type="text/html"></link>
    <summary type="text">From my daily driver Ubuntu machine I often open nautilus, dolphin, etc. and delete a file here or there on my NAS... turns out Ubuntu sends thse file to ON...</summary>
    <content type="html">&lt;p&gt;From my daily driver Ubuntu machine I often open nautilus, dolphin, etc. and delete a file here or there on my NAS&amp;hellip; turns out Ubuntu sends thse file to &lt;code&gt;.Trash-100&lt;/code&gt; ON THE NAS so I&amp;rsquo;m effectively just moving that file and not freeing up any space&amp;hellip;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Plug Snapshot!</title>
    <id>https://pype.dev/plug-snapshot/</id>
    <updated>2022-05-17T15:45:49Z</updated>
    <published>2022-05-17T15:45:49Z</published>
    <link href="https://pype.dev/plug-snapshot/" rel="alternate" type="text/html"></link>
    <summary type="text">:PlugSnapshot, :w ~/dotfiles/nvim/snapshot.vim... keep your config safe with git!</summary>
    <content type="html">&lt;p&gt;:PlugSnapshot, :w ~/dotfiles/nvim/snapshot.vim&amp;hellip; keep your config safe with git!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Filepath Completion in Neovim</title>
    <id>https://pype.dev/filepath-completion-in-neovim/</id>
    <updated>2022-05-17T14:03:27Z</updated>
    <published>2022-05-17T14:03:27Z</published>
    <link href="https://pype.dev/filepath-completion-in-neovim/" rel="alternate" type="text/html"></link>
    <summary type="text">I&#39;ve had in my plugins for ever but didn&#39;t notice until recently that I wasn&#39;t getting any filepath completion in vim!</summary>
    <content type="html">&lt;p&gt;I&amp;rsquo;ve had &lt;code&gt;Plug &#39;hrsh7th/cmp-path&#39;&lt;/code&gt; in my plugins for ever but didn&amp;rsquo;t notice&#xA;until recently that I wasn&amp;rsquo;t getting any filepath completion in vim!&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Fuller setup instructions below the TLDR&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;h1 id=&#34;tl-dr&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;TL;DR&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;Turns out I need to not be a dope and configure nvim-cmp to actually use it&amp;hellip;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;local&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cmp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;require&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;cmp&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;cmp.setup&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;-- removed rest of setup - see the rest in my dotfiles&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;sources&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cmp.config&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sources&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;path&amp;#39;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;-- This needs to be here!&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;my-setup&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;My Setup&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;For the sake of completeness here is how I currently (May 2022) configure completion in Neovim usin &lt;code&gt;nvim-cmp&lt;/code&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;plugins&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Plugins&lt;/span&gt; &lt;a href=&#34;#plugins&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I keep all my plugins in &lt;code&gt;plugins.vim&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;call&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;plug&lt;/span&gt;#&lt;span class=&#34;nx&#34;&gt;begin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;:&lt;span class=&#34;nx&#34;&gt;plug_dir&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;Plug&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;neovim/nvim-lspconfig&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;Plug&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;hrsh7th/cmp-nvim-lsp&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;Plug&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;hrsh7th/cmp-buffer&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;Plug&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;hrsh7th/cmp-path&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;Plug&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;hrsh7th/cmp-cmdline&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;Plug&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;hrsh7th/nvim-cmp&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;&amp;#34; For ultisnips users.&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;!--&lt;/span&gt; &lt;span class=&#34;c&#34;&gt;&amp;#34; Plug &amp;#39;SirVer/ultisnips&amp;#39; --&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;!--&lt;/span&gt; &lt;span class=&#34;c&#34;&gt;&amp;#34; Plug &amp;#39;quangnguyen30192/cmp-nvim-ultisnips&amp;#39; --&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;call&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;plug&lt;/span&gt;#&lt;span class=&#34;nx&#34;&gt;end&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;vim-settings&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Vim Settings&lt;/span&gt; &lt;a href=&#34;#vim-settings&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;My vim settings are also kept in their own file, &lt;code&gt;settings.vim&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;set&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;completeopt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;menu&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;menuone&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;noselect&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;nvim-cmp-configuration&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;nvim-cmp configuration&lt;/span&gt; &lt;a href=&#34;#nvim-cmp-configuration&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I have a &lt;code&gt;cmp.lua&lt;/code&gt; file that gets sourced in &lt;code&gt;init.lua&lt;/code&gt; (file structure explained below) for configuring cmp.&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;-- Setup nvim-cmp.&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;local&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cmp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;require&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;cmp&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;cmp.setup&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;snippet&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;-- REQUIRED - you must specify a snippet engine&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;expand&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;c1&#34;&gt;-- For `ultisnips` user.&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;n&#34;&gt;vim.fn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;UltiSnips#Anon&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;](&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args.body&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kr&#34;&gt;end&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;window&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;n&#34;&gt;completion&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cmp.config&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;window.bordered&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;mapping&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;lt;Down&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cmp.mapping&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;select_next_item&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;behavior&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cmp.SelectBehavior&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Select&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;lt;Up&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cmp.mapping&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;select_prev_item&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;behavior&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cmp.SelectBehavior&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Select&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;lt;C-d&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cmp.mapping&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;scroll_docs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;lt;C-f&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cmp.mapping&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;scroll_docs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;lt;C-Space&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cmp.mapping&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;complete&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;lt;C-e&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cmp.mapping&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;close&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;lt;Tab&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cmp.mapping&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cmp.mapping&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;select_next_item&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;i&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;s&amp;#39;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;lt;CR&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cmp.mapping&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;confirm&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;n&#34;&gt;behavior&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cmp.ConfirmBehavior&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Replace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;n&#34;&gt;select&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;sources&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cmp.config&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sources&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;nvim_lsp&amp;#39;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;ultisnips&amp;#39;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;buffer&amp;#39;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;path&amp;#39;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;tmux&amp;#39;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;sources&lt;/code&gt; section is what was key for this post&amp;hellip;&lt;/p&gt;&#xA;&lt;h1 id=&#34;piecing-it-together&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Piecing it together!&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;My &lt;code&gt;init.vim&lt;/code&gt; sources plugins and then settings and then finally calls &lt;code&gt;init.lua&lt;/code&gt;.&#xA;&lt;code&gt;init.lua&lt;/code&gt; sources my &lt;code&gt;cmp.lua&lt;/code&gt; file and BANG! auto-completion.&lt;/p&gt;&#xA;&lt;h2 id=&#34;more-sources&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;More sources&lt;/span&gt; &lt;a href=&#34;#more-sources&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;hrsh7th&amp;rsquo;s wiki for &lt;code&gt;nvim-cmp&lt;/code&gt; is &lt;a href=&#34;https://github.com/hrsh7th/nvim-cmp/wiki/List-of-sources&#34;&gt;here&lt;/a&gt; and has example configs as well as a list of sources&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Don&amp;rsquo;t forget to configure and not just install!&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/nicpayne713/dotfiles&#34;&gt;my dotfiles&lt;/a&gt;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Forms with FastAPI and Jinja</title>
    <id>https://pype.dev/fastapi-jinja-forms/</id>
    <updated>2022-05-15T00:00:00Z</updated>
    <published>2022-05-15T00:00:00Z</published>
    <link href="https://pype.dev/fastapi-jinja-forms/" rel="alternate" type="text/html"></link>
    <summary type="text">I just started using FastAPI for a home project and needed to pass back a dynamic number of values from a form rendered with jinja...</summary>
    <content type="html">&lt;p&gt;I just started using FastAPI for a home project and needed to pass back a&#xA;dynamic number of values from a form rendered with jinja&amp;hellip;&lt;/p&gt;&#xA;&lt;h1 id=&#34;dynamic-values&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Dynamic Values&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;The jinja templating for rendering HTML based on something like a python iterable is nice and easy&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;data is the result of a database query, and item is each row, so the dot notation is the value of each column basically in that row&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;&amp;lt;form method=&amp;#34;post&amp;#34;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;{%&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;item&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;cp&#34;&gt;%}&lt;/span&gt;&lt;span class=&#34;x&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;    &amp;lt;div class=&amp;#34;form-check &amp;#34;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;        &amp;lt;input class=&amp;#34;form-check-input&amp;#34;  name=&amp;#34;item_&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;{{&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;item.id&lt;/span&gt; &lt;span class=&#34;cp&#34;&gt;}}&lt;/span&gt;&lt;span class=&#34;x&#34;&gt;&amp;#34; id=&amp;#34;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;{{&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;item.name&lt;/span&gt; &lt;span class=&#34;cp&#34;&gt;}}&lt;/span&gt;&lt;span class=&#34;x&#34;&gt;&amp;#34; value=&amp;#34;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;{{&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;item.id&lt;/span&gt; &lt;span class=&#34;cp&#34;&gt;}}&lt;/span&gt;&lt;span class=&#34;x&#34;&gt;&amp;#34; type=&amp;#34;checkbox&amp;#34;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;        &amp;lt;label class=&amp;#34;form-check-label&amp;#34; for=&amp;#34;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;{{&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;item.id&lt;/span&gt; &lt;span class=&#34;cp&#34;&gt;}}&lt;/span&gt;&lt;span class=&#34;x&#34;&gt;&amp;#34; &amp;gt; Label for: &lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;{{&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;item.name&lt;/span&gt; &lt;span class=&#34;cp&#34;&gt;}}&lt;/span&gt;&lt;span class=&#34;x&#34;&gt; &amp;lt;/label&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;    &amp;lt;/div&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;{%&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;endfor&lt;/span&gt; &lt;span class=&#34;cp&#34;&gt;%}&lt;/span&gt;&lt;span class=&#34;x&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;&amp;lt;button type=&amp;#34;submit&amp;#34; class=&amp;#34;submit btn btn-xl btn-outline-danger&amp;#34; &amp;gt;Remove&amp;lt;/button&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;&amp;lt;/form&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This form generates a row with a checkbox for every &lt;code&gt;item&lt;/code&gt; in &lt;code&gt;data&lt;/code&gt; (in my&#xA;case each &lt;code&gt;item&lt;/code&gt; is an existing row in my table). it?&lt;/p&gt;&#xA;&lt;p&gt;The way to pass back all those values is pretty straight forward (after hours of messing around that is!)&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# I hate it when tutorials don&amp;#39;t show ALL relevant pieces to the blurb&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;starlette.status&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;status&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;fastapi&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;APIRouter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Depends&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Form&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Request&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;fastapi.encoders&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;jsonable_encoder&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;fastapi.responses&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;HTMLResponse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;RedirectResponse&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;fastapi.templating&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Jinja2Templates&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;sqlalchemy.orm&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Session&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;app.session.session&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;create_get_session&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;router&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;APIRouter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;templates&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Jinja2Templates&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;directory&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;templates/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@router.post&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/my_route/do_something_with_form&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;response_class&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;HTMLResponse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;async&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;delete_rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Session&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Depends&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;create_get_session&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;form_data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get_form&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;jsonable_encoder&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;form_data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# data = {&amp;#34;item_1&amp;#34;: 1, &amp;#34;item_2&amp;#34;: 2, ... &amp;#34;item_N&amp;#34;: N}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;RedirectResponse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;status_code&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;HTTP_302_FOUND&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We &lt;code&gt;await request.get_form()&lt;/code&gt; and after encoding the data we get a dictionary with key/value pairs of the name/value from the form!&lt;/p&gt;&#xA;&lt;p&gt;This took me quite a long time to figure out in part because most of the Google-able resources are still on Flask&amp;hellip;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Dynamic-Form-Values-With-Jinja-And-Fastapi</title>
    <id>https://pype.dev/dynamic-form-values-with-jinja-and-fastapi/</id>
    <updated>2022-05-15T00:00:00Z</updated>
    <published>2022-05-15T00:00:00Z</published>
    <link href="https://pype.dev/dynamic-form-values-with-jinja-and-fastapi/" rel="alternate" type="text/html"></link>
    <summary type="text">I&#39;m currently working on a self-hostable wish list app using FastAPI so we can finally drop Amazon forever. (The lists funcionality has been super handy for...</summary>
    <content type="html">&lt;p&gt;I&amp;rsquo;m currently working on a self-hostable wish list app using FastAPI so we can&#xA;finally drop Amazon forever. (The lists funcionality has been super handy for&#xA;sharing holiday gift ideas with the famj!)&lt;/p&gt;&#xA;&lt;h1 id=&#34;fastapi&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;FastAPI&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;FastAPI is an amazing framework for quickly building APIs with Python. I will have a slightly longer post about my brief experience with it coming later&amp;hellip;&lt;/p&gt;&#xA;&lt;h1 id=&#34;jinja-forms-and-fastapi&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Jinja, Forms, and FastAPI&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;One of the last things I needed to figure out in my app was how to generate a&#xA;form in a Jinja template with a dynamic number of inputs and then pass all the&#xA;inputs to the backend to perform a database operation (my exact case was&#xA;removing rows from a table).&lt;/p&gt;&#xA;&lt;h2 id=&#34;explicit-values&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Explicit Values&lt;/span&gt; &lt;a href=&#34;#explicit-values&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;The way to pass back explicit variables is really easy&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;Our form would look like this (I&amp;rsquo;m using bootstrap CSS)&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;&amp;lt;form method=&amp;#34;post&amp;#34;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;    &amp;lt;div class=&amp;#34;form-check &amp;#34;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;        &amp;lt;input class=&amp;#34;form-check-input&amp;#34;  name=&amp;#34;item_1&amp;#34; id=&amp;#34;itemOne&amp;#34; value=&amp;#34;1&amp;#34; type=&amp;#34;checkbox&amp;#34;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;        &amp;lt;label class=&amp;#34;form-check-label&amp;#34; for=&amp;#34;itemOne&amp;#34; &amp;gt; A label for this item &amp;lt;/label&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;    &amp;lt;/div&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;    &amp;lt;div class=&amp;#34;form-check &amp;#34;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;        &amp;lt;input class=&amp;#34;form-check-input&amp;#34;  name=&amp;#34;item_2&amp;#34; id=&amp;#34;itemTwo&amp;#34; value=&amp;#34;2&amp;#34; type=&amp;#34;checkbox&amp;#34;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;        &amp;lt;label class=&amp;#34;form-check-label&amp;#34; for=&amp;#34;itemTwo&amp;#34; &amp;gt; A label for item 2 &amp;lt;/label&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;    &amp;lt;/div&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;&amp;lt;button type=&amp;#34;submit&amp;#34; class=&amp;#34;submit btn btn-xl&amp;#34; &amp;gt;Submit&amp;lt;/button&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;&amp;lt;/form&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So what is this? This form will have 2 rows with the lables you see in &lt;code&gt;&amp;lt;label&amp;gt; &amp;lt;/label&amp;gt;&lt;/code&gt; and checkboxes that when checked would have the value &lt;code&gt;value&lt;/code&gt; in each&#xA;&lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; line.&lt;/p&gt;&#xA;&lt;p&gt;So our backend might looks something like this&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;I&amp;rsquo;m keeping all the imports and stuff here to show where they come from but I won&amp;rsquo;t discuss it all here - that&amp;rsquo;ll be in a future post&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;starlette.status&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;status&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;fastapi&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;APIRouter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Depends&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Form&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Request&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;fastapi.encoders&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;jsonable_encoder&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;fastapi.responses&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;HTMLResponse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;RedirectResponse&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;fastapi.templating&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Jinja2Templates&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;sqlalchemy.orm&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Session&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;app.session.session&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;create_get_session&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;router&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;APIRouter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;templates&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Jinja2Templates&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;directory&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;templates/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@router.post&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/my_route/do_something_with_form&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;response_class&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;HTMLResponse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;async&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;delete_rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;item_1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Form&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;item_2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Form&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Session&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Depends&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;create_get_session&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;item_1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# will just print 1 to the console where fastapi is running if the checkbox was checked&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;item_2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# will just print 1 to the console where fastapi is running if the checkbox was checked&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;RedirectResponse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;status_code&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;HTTP_302_FOUND&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;dynamic-values&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Dynamic values&lt;/span&gt; &lt;a href=&#34;#dynamic-values&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;That&amp;rsquo;s all pretty simple&amp;hellip; pass back values by the name in the form&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;What about a form that&amp;rsquo;s generated dynamically? This is my case since I display a row/checkbox for every row in my table so my form looks like this&amp;hellip;&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;data is the result of a database query, and item is each row, so the dot notation is the value of each column basically in that row&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;&amp;lt;form method=&amp;#34;post&amp;#34;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;{%&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;item&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;cp&#34;&gt;%}&lt;/span&gt;&lt;span class=&#34;x&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;    &amp;lt;div class=&amp;#34;form-check &amp;#34;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;        &amp;lt;input class=&amp;#34;form-check-input&amp;#34;  name=&amp;#34;item_&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;{{&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;item.id&lt;/span&gt; &lt;span class=&#34;cp&#34;&gt;}}&lt;/span&gt;&lt;span class=&#34;x&#34;&gt;&amp;#34; id=&amp;#34;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;{{&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;item.name&lt;/span&gt; &lt;span class=&#34;cp&#34;&gt;}}&lt;/span&gt;&lt;span class=&#34;x&#34;&gt;&amp;#34; value=&amp;#34;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;{{&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;item.id&lt;/span&gt; &lt;span class=&#34;cp&#34;&gt;}}&lt;/span&gt;&lt;span class=&#34;x&#34;&gt;&amp;#34; type=&amp;#34;checkbox&amp;#34;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;        &amp;lt;label class=&amp;#34;form-check-label&amp;#34; for=&amp;#34;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;{{&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;item.id&lt;/span&gt; &lt;span class=&#34;cp&#34;&gt;}}&lt;/span&gt;&lt;span class=&#34;x&#34;&gt;&amp;#34; &amp;gt; Label for: &lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;{{&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;item.name&lt;/span&gt; &lt;span class=&#34;cp&#34;&gt;}}&lt;/span&gt;&lt;span class=&#34;x&#34;&gt; &amp;lt;/label&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;    &amp;lt;/div&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;{%&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;endfor&lt;/span&gt; &lt;span class=&#34;cp&#34;&gt;%}&lt;/span&gt;&lt;span class=&#34;x&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;&amp;lt;button type=&amp;#34;submit&amp;#34; class=&amp;#34;submit btn btn-xl btn-outline-danger&amp;#34; &amp;gt;Remove&amp;lt;/button&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;&amp;lt;/form&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;x&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This form generates a row with a checkbox for every &lt;code&gt;item&lt;/code&gt; in &lt;code&gt;data&lt;/code&gt; (in my&#xA;case each &lt;code&gt;item&lt;/code&gt; is an existing row in my table). Now I started scratching my&#xA;head on how to pass an unknown number of inputs to my backend of FastAPI wants&#xA;each input explicitly defined and typed&amp;hellip; I can&amp;rsquo;t just pass the form back&#xA;becuase that&amp;rsquo;s not a thing so what&amp;rsquo;s the way to do it?&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# same stuff as above, only showing post method here&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@router.post&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/my_route/do_something_with_form&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;response_class&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;HTMLResponse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;async&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;delete_rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Session&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Depends&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;create_get_session&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;form_data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get_form&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;jsonable_encoder&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;form_data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# data = {&amp;#34;item_1&amp;#34;: 1, &amp;#34;item_2&amp;#34;: 2, ... &amp;#34;item_N&amp;#34;: N}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;RedirectResponse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;status_code&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;HTTP_302_FOUND&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We &lt;code&gt;await request.get_form()&lt;/code&gt; and after encoding the data we get a dictionary with key/value pairs of the name/value from the form!&lt;/p&gt;&#xA;&lt;p&gt;This took me quite a long time to figure out in part because most of the Google-able resources are still on Flask&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;I look forward to my wish list app maturing and I hope this helps someone working with FastAPI!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Plug-Snapshot-To-Save-Your-Life</title>
    <id>https://pype.dev/plug-snapshot-to-save-your-life/</id>
    <updated>2022-05-13T00:00:00Z</updated>
    <published>2022-05-13T00:00:00Z</published>
    <link href="https://pype.dev/plug-snapshot-to-save-your-life/" rel="alternate" type="text/html"></link>
    <summary type="text">If you use vim-plug for managing your vim plugins, do yourself a favor and snapshot your plugins before upgrading!</summary>
    <content type="html">&lt;p&gt;If you use vim-plug for managing your vim plugins, do yourself a favor and snapshot your plugins before upgrading!&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;:PlugSnapshot&lt;/code&gt;  creates a vim.snapshot file that you can use to restore your plugin versions with &lt;code&gt;vim -S snapshot.vim&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;The snapshot file looks like this:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;❯ cat snapshot.vim&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;&amp;#34; Generated by vim-plug&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;&amp;#34; Tue 17 May 2022 03:44:29 PM CDT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;&amp;#34; :source this file in vim to restore the snapshot&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;&amp;#34; or execute: vim -S snapshot.vim&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;Telegraph.nvim&amp;#39;].commit = &amp;#39;92e472f4e83acd60eb3766168e66d02718bfefe0&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;TrueZen.nvim&amp;#39;].commit = &amp;#39;508b977d71650da5c9243698614a9a1416f116d4&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;ariake-vim-colors&amp;#39;].commit = &amp;#39;9fb35f1255e475631c9df24ecc5485a40360cc7b&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;auto-pairs&amp;#39;].commit = &amp;#39;39f06b873a8449af8ff6a3eee716d3da14d63a76&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;bufutils.vim&amp;#39;].commit = &amp;#39;4634feb1312fd73fab66cfaa860e7af3abde935b&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;cmp-buffer&amp;#39;].commit = &amp;#39;12463cfcd9b14052f9effccbf1d84caa7a2d57f0&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;cmp-cmdline&amp;#39;].commit = &amp;#39;c36ca4bc1dedb12b4ba6546b96c43896fd6e7252&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;cmp-nvim-lsp&amp;#39;].commit = &amp;#39;e6b5feb2e6560b61f31c756fb9231a0d7b10c73d&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;cmp-nvim-ultisnips&amp;#39;].commit = &amp;#39;21f02b62deb409ce69928a23406076bd0043ddbc&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;cmp-path&amp;#39;].commit = &amp;#39;466b6b8270f7ba89abd59f402c73f63c7331ff6e&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;cmp-spell&amp;#39;].commit = &amp;#39;5602f1a0de7831f8dad5b0c6db45328fbd539971&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;compe-tabnine&amp;#39;].commit = &amp;#39;33e4af509c27da9ef2c9c3002c01e3ec031797d4&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;coverage-highlight.vim&amp;#39;].commit = &amp;#39;864e03679ea4168661501246147893cc82020917&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;diffurcate.vim&amp;#39;].commit = &amp;#39;b804675072220ff7c7ebcd24a028aa4aa35f09cc&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;fzf&amp;#39;].commit = &amp;#39;6dcf5c3d7d6c321b17e6a5673f1533d6e8350462&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;fzf.vim&amp;#39;].commit = &amp;#39;d5f1f8641b24c0fd5b10a299824362a2a1b20ae0&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;git-blame.vim&amp;#39;].commit = &amp;#39;9d144b7bed5d8f1c9259551768b7f3b3d1294917&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;harpoon&amp;#39;].commit = &amp;#39;d3d3d22b6207f46f8ca64946f4d781e975aec0fc&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;instant.nvim&amp;#39;].commit = &amp;#39;c02d72267b12130609b7ad39b76cf7f4a3bc9554&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;lsp-colors.nvim&amp;#39;].commit = &amp;#39;517fe3ab6b63f9907b093bc9443ef06b56f804f3&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;lsp_extensions.nvim&amp;#39;].commit = &amp;#39;4011f4aec61ba59c734f5dbf52e91f258b99d985&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;lspkind-nvim&amp;#39;].commit = &amp;#39;57e5b5dfbe991151b07d272a06e365a77cc3d0e7&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;lspsaga.nvim&amp;#39;].commit = &amp;#39;8dde091a61ab07f639baaa82b456d3508d0aa7e8&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;neoformat&amp;#39;].commit = &amp;#39;409ebbba9f4b568ea87ab4f2de90a645cf5d000a&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;neovim-fuzzy&amp;#39;].commit = &amp;#39;0bef4e1a81c65fc05d31380dd74454bd67733837&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;nerdtree&amp;#39;].commit = &amp;#39;eed488b1cd1867bd25f19f90e10440c5cc7d6424&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;nerdtree-visual-selection&amp;#39;].commit = &amp;#39;05427635ff053a2c542fcf8d7c3744c72575e76c&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;nvim-cmp&amp;#39;].commit = &amp;#39;a226b6a4ff72e5e809ed17734318233fb25c87f3&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;nvim-compe&amp;#39;].commit = &amp;#39;d186d739c54823e0b010feb205c6f97792322c08&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;nvim-lspconfig&amp;#39;].commit = &amp;#39;9ff2a06cebd4c8c3af5259d713959ab310125bec&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;nvim-lspinstall&amp;#39;].commit = &amp;#39;79ec2425d6b39cdcb69d379f3e56847f49be73eb&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;nvim-treesitter&amp;#39;].commit = &amp;#39;10d57b3ec14cac0b6b759e1eb5594617b8a7e883&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;nvim-treesitter-textobjects&amp;#39;].commit = &amp;#39;094e8ad3cc839e825f8dcc91352837653e365a8f&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;nvim-web-devicons&amp;#39;].commit = &amp;#39;bdd43421437f2ef037e0dafeaaaa62b31d35ef2f&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;playground&amp;#39;].commit = &amp;#39;71b00a3c665298e5155ad64a9020135808d4e3e8&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;plenary.nvim&amp;#39;].commit = &amp;#39;25b3475b97f241e6f76249747bc209e70c5d2ec8&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;popup.nvim&amp;#39;].commit = &amp;#39;b7404d35d5d3548a82149238289fa71f7f6de4ac&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;syntastic&amp;#39;].commit = &amp;#39;b7f4f71539038d33f173bfa72631737da049575a&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;tabular&amp;#39;].commit = &amp;#39;339091ac4dd1f17e225fe7d57b48aff55f99b23a&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;targets.vim&amp;#39;].commit = &amp;#39;8d6ff2984cdfaebe5b7a6eee8f226a6dd1226f2d&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;telescope-fzy-native.nvim&amp;#39;].commit = &amp;#39;7b3d2528102f858036627a68821ccf5fc1d78ce4&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;telescope.nvim&amp;#39;].commit = &amp;#39;39b12d84e86f5054e2ed98829b367598ae53ab41&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;termopen.vim&amp;#39;].commit = &amp;#39;3194a991a18a9be2fd9fcf8c4c55fe990c04b2bd&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;tokyonight.nvim&amp;#39;].commit = &amp;#39;8223c970677e4d88c9b6b6d81bda23daf11062bb&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;trouble.nvim&amp;#39;].commit = &amp;#39;da61737d860ddc12f78e638152834487eabf0ee5&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;ultisnips&amp;#39;].commit = &amp;#39;f5ccf0977c611ffd774ca180774959301baaffad&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;undotree&amp;#39;].commit = &amp;#39;08e259be24d4476c1ee745dc735eefd44f90efdc&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;vim-airline&amp;#39;].commit = &amp;#39;c4655701431a9c79704c827fd88a4783ec946879&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;vim-airline-themes&amp;#39;].commit = &amp;#39;97cf3e6e638f936187d5f6e9b5eb1bdf0a4df256&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;vim-be-good&amp;#39;].commit = &amp;#39;bc499a06c14c729b22a6cc7e730a9fbc44d4e737&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;vim-commentary&amp;#39;].commit = &amp;#39;3654775824337f466109f00eaf6759760f65be34&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;vim-devicons&amp;#39;].commit = &amp;#39;a2258658661e42dd4cdba4958805dbad1fe29ef4&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;vim-dispatch&amp;#39;].commit = &amp;#39;00e77d90452e3c710014b26dc61ea919bc895e92&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;vim-flake8&amp;#39;].commit = &amp;#39;a99054ef98e8fdaefa1315af4649138bcadbfdf7&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;vim-floaterm&amp;#39;].commit = &amp;#39;ab7876f86c05c1935eb23a193f4f276132902ac1&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;vim-fugitive&amp;#39;].commit = &amp;#39;f529acef74b4266d94f22414c60b4a8930c1e0f3&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;vim-gitbranch&amp;#39;].commit = &amp;#39;1a8ba866f3eaf0194783b9f8573339d6ede8f1ed&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;vim-indent-object&amp;#39;].commit = &amp;#39;5c5b24c959478929b54a9e831a8e2e651a465965&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;vim-nerdtree-syntax-highlight&amp;#39;].commit = &amp;#39;5178ee4d7f4e7761187df30bb709f703d91df18a&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;vim-polyglot&amp;#39;].commit = &amp;#39;38282d58387cff48ac203f6912c05e4c8686141b&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;vim-pydocstring&amp;#39;].commit = &amp;#39;f6e3c52bfaf4b4f76dab4d84e75b94199d5f3b9c&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;vim-quicklink&amp;#39;].commit = &amp;#39;021167741588555501594e1fc31f130b16acefa0&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;vim-repeat&amp;#39;].commit = &amp;#39;24afe922e6a05891756ecf331f39a1f6743d3d5a&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;vim-signify&amp;#39;].commit = &amp;#39;69498f6d49f3eeac06870012416dd9bf867b84f3&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;vim-sneak&amp;#39;].commit = &amp;#39;94c2de47ab301d476a2baec9ffda07367046bec9&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;vim-snippets&amp;#39;].commit = &amp;#39;6f270bb2d26c38765ff2243e9337c65f8a96a28b&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;vim-startify&amp;#39;].commit = &amp;#39;81e36c352a8deea54df5ec1e2f4348685569bed2&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;vim-surround&amp;#39;].commit = &amp;#39;bf3480dc9ae7bea34c78fbba4c65b4548b5b1fea&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;vim-test&amp;#39;].commit = &amp;#39;2240d7a4b868cb594b7d83544e1b6db4df806e5e&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;vim-tmux-runner&amp;#39;].commit = &amp;#39;54767911fd5e6e2d8e493847149e315ac2e6531a&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;vim-ultest&amp;#39;].commit = &amp;#39;6978fd32e3ca2c1c5591884eea0d57a7ee43d212&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;vim-visualstar&amp;#39;].commit = &amp;#39;a18cd0e7a03311ac709595c1d261ed44b45c9098&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;vimtex&amp;#39;].commit = &amp;#39;dfaca59bbbf0079ab1b4f159337ae7f17d1b5289&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;silent! let g:plugs[&amp;#39;which-key.nvim&amp;#39;].commit = &amp;#39;bd4411a2ed4dd8bb69c125e339d837028a6eea71&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;PlugUpdate!&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Python-Eval</title>
    <id>https://pype.dev/python-eval/</id>
    <updated>2022-05-12T00:00:00Z</updated>
    <published>2022-05-12T00:00:00Z</published>
    <link href="https://pype.dev/python-eval/" rel="alternate" type="text/html"></link>
    <content type="html">&lt;h1 id=&#34;todo&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;TODO&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;title&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;my Title&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;eval&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#34;my&amp;#34; in title&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;hello, world&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;formatting&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Dataframe-To-Styled-Html</title>
    <id>https://pype.dev/dataframe-to-styled-html/</id>
    <updated>2022-05-07T00:00:00Z</updated>
    <published>2022-05-07T00:00:00Z</published>
    <link href="https://pype.dev/dataframe-to-styled-html/" rel="alternate" type="text/html"></link>
    <summary type="text">I wrote up a little on exporting DataFrames to markdown and html here</summary>
    <content type="html">&lt;p&gt;I wrote up a little on exporting DataFrames to markdown and html &lt;a href=&#34;/dataframe-to-markdown&#34;&gt;here&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;But I&amp;rsquo;ve been playing with a web app for with lists and while I&amp;rsquo;m toying around I learned you can actually give your tables some style with some simple css classes!&lt;/p&gt;&#xA;&lt;h1 id=&#34;to-html&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;To HTML&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;Reminder that if you have a dataframe, &lt;code&gt;df&lt;/code&gt;, you can &lt;code&gt;df.to_html()&lt;/code&gt; to get an HTML table of your dataframe.&lt;/p&gt;&#xA;&lt;p&gt;Well you can pass some &lt;code&gt;classes&lt;/code&gt; to make it look super nice!&lt;/p&gt;&#xA;&lt;h1 id=&#34;classes-and-css&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Classes and CSS&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;I don&amp;rsquo;t know anything really about CSS so I won&amp;rsquo;t pretend otherwise, but as I was learning about bootstrap that&amp;rsquo;s where I stumbled upon this&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;There are several classes you can pass but I found really good luck with &lt;code&gt;table-bordered&lt;/code&gt; and &lt;code&gt;table-dark&lt;/code&gt; for my use case&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;df.to_html(classes=[&amp;quot;table table-bordered table-dark&amp;quot;])&lt;/code&gt;&lt;/p&gt;&#xA;&lt;table border=&#34;1&#34; class=&#34;dataframe table table-bordered table-dark&#34;&gt;  &lt;thead&gt;&#xA;&lt;tr style=&#34;text-align: right;&#34;&gt;      &lt;th&gt;Unnamed: 0&lt;/th&gt;      &lt;th&gt;mpg&lt;/th&gt;&#xA;&lt;th&gt;cyl&lt;/th&gt;      &lt;th&gt;disp&lt;/th&gt;      &lt;th&gt;hp&lt;/th&gt;      &lt;th&gt;drat&lt;/th&gt;&#xA;&lt;th&gt;wt&lt;/th&gt;      &lt;th&gt;qsec&lt;/th&gt;      &lt;th&gt;vs&lt;/th&gt;      &lt;th&gt;am&lt;/th&gt;&#xA;&lt;th&gt;gear&lt;/th&gt;      &lt;th&gt;carb&lt;/th&gt;    &lt;/tr&gt;  &lt;/thead&gt;  &lt;tbody&gt;    &lt;tr&gt;&#xA;&lt;td&gt;Mazda RX4&lt;/td&gt;      &lt;td&gt;21.0&lt;/td&gt;      &lt;td&gt;6&lt;/td&gt;      &lt;td&gt;160.0&lt;/td&gt;&#xA;&lt;td&gt;110&lt;/td&gt;      &lt;td&gt;3.90&lt;/td&gt;      &lt;td&gt;2.620&lt;/td&gt;      &lt;td&gt;16.46&lt;/td&gt;&#xA;&lt;td&gt;0&lt;/td&gt;      &lt;td&gt;1&lt;/td&gt;      &lt;td&gt;4&lt;/td&gt;      &lt;td&gt;4&lt;/td&gt;    &lt;/tr&gt;    &lt;tr&gt;&#xA;&lt;td&gt;Mazda RX4 Wag&lt;/td&gt;      &lt;td&gt;21.0&lt;/td&gt;      &lt;td&gt;6&lt;/td&gt;      &lt;td&gt;160.0&lt;/td&gt;&#xA;&lt;td&gt;110&lt;/td&gt;      &lt;td&gt;3.90&lt;/td&gt;      &lt;td&gt;2.875&lt;/td&gt;      &lt;td&gt;17.02&lt;/td&gt;&#xA;&lt;td&gt;0&lt;/td&gt;      &lt;td&gt;1&lt;/td&gt;      &lt;td&gt;4&lt;/td&gt;      &lt;td&gt;4&lt;/td&gt;    &lt;/tr&gt;    &lt;tr&gt;&#xA;&lt;td&gt;Datsun 710&lt;/td&gt;      &lt;td&gt;22.8&lt;/td&gt;      &lt;td&gt;4&lt;/td&gt;      &lt;td&gt;108.0&lt;/td&gt;&#xA;&lt;td&gt;93&lt;/td&gt;      &lt;td&gt;3.85&lt;/td&gt;      &lt;td&gt;2.320&lt;/td&gt;      &lt;td&gt;18.61&lt;/td&gt;&#xA;&lt;td&gt;1&lt;/td&gt;      &lt;td&gt;1&lt;/td&gt;      &lt;td&gt;4&lt;/td&gt;      &lt;td&gt;1&lt;/td&gt;    &lt;/tr&gt;    &lt;tr&gt;&#xA;&lt;td&gt;Hornet 4 Drive&lt;/td&gt;      &lt;td&gt;21.4&lt;/td&gt;      &lt;td&gt;6&lt;/td&gt;      &lt;td&gt;258.0&lt;/td&gt;&#xA;&lt;td&gt;110&lt;/td&gt;      &lt;td&gt;3.08&lt;/td&gt;      &lt;td&gt;3.215&lt;/td&gt;      &lt;td&gt;19.44&lt;/td&gt;&#xA;&lt;td&gt;1&lt;/td&gt;      &lt;td&gt;0&lt;/td&gt;      &lt;td&gt;3&lt;/td&gt;      &lt;td&gt;1&lt;/td&gt;    &lt;/tr&gt;    &lt;tr&gt;&#xA;&lt;td&gt;Hornet Sportabout&lt;/td&gt;      &lt;td&gt;18.7&lt;/td&gt;      &lt;td&gt;8&lt;/td&gt;&#xA;&lt;td&gt;360.0&lt;/td&gt;      &lt;td&gt;175&lt;/td&gt;      &lt;td&gt;3.15&lt;/td&gt;      &lt;td&gt;3.440&lt;/td&gt;&#xA;&lt;td&gt;17.02&lt;/td&gt;      &lt;td&gt;0&lt;/td&gt;      &lt;td&gt;0&lt;/td&gt;      &lt;td&gt;3&lt;/td&gt;      &lt;td&gt;2&lt;/td&gt;&#xA;&lt;/tr&gt;  &lt;/tbody&gt;&lt;/table&gt;&#xA;&lt;h1 id=&#34;you-try-it&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;You try it!&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;Crack open ipython and make a dataframe, then &lt;code&gt;df.to_html(classes=[&amp;quot;table table-bordered table-dark&amp;quot;])&lt;/code&gt;, copy the output (minus the quote marks ipython uses to denote the string type) that into &lt;code&gt;my-file.html&lt;/code&gt;, open that up in a browser and be amazed!&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;For added effeciency try using pyperclip to copy the output right to your clipboard!&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;&lt;code&gt;pip install pyperclip&lt;/code&gt; and then &lt;code&gt;pyperclip.copy(df.to_html(classes=[&amp;quot;table table-bordered table-dark&amp;quot;]))&lt;/code&gt;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Dataframe-To-Markdown</title>
    <id>https://pype.dev/dataframe-to-markdown/</id>
    <updated>2022-05-07T00:00:00Z</updated>
    <published>2022-05-07T00:00:00Z</published>
    <link href="https://pype.dev/dataframe-to-markdown/" rel="alternate" type="text/html"></link>
    <summary type="text">s are pretty sweet data structures in Python.</summary>
    <content type="html">&lt;h1 id=&#34;pandas&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Pandas&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;&lt;code&gt;pandas.DataFrame&lt;/code&gt;s are pretty sweet data structures in Python.&lt;/p&gt;&#xA;&lt;p&gt;I do a lot of work with tabular data and one thing I have incorporated into some of that work is automatic data summary reports by throwing the first few, or several relevant, rows of a dataframe at a point in a pipeline into a markdown file.&lt;/p&gt;&#xA;&lt;p&gt;Pandas has a method on DataFrames that makes this 100% trivial!&lt;/p&gt;&#xA;&lt;h1 id=&#34;the-method&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Method&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;Say we have a dataframe, &lt;code&gt;df&lt;/code&gt;&amp;hellip; then it&amp;rsquo;s literally just: &lt;code&gt;df.to_markdown()&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;n&#34;&gt;Unnamed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;   &lt;span class=&#34;n&#34;&gt;mpg&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;cyl&lt;/span&gt;   &lt;span class=&#34;n&#34;&gt;disp&lt;/span&gt;   &lt;span class=&#34;n&#34;&gt;hp&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;drat&lt;/span&gt;     &lt;span class=&#34;n&#34;&gt;wt&lt;/span&gt;   &lt;span class=&#34;n&#34;&gt;qsec&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;vs&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;am&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;gear&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;carb&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;          &lt;span class=&#34;n&#34;&gt;Mazda&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;RX4&lt;/span&gt;  &lt;span class=&#34;mf&#34;&gt;21.0&lt;/span&gt;    &lt;span class=&#34;mi&#34;&gt;6&lt;/span&gt;  &lt;span class=&#34;mf&#34;&gt;160.0&lt;/span&gt;  &lt;span class=&#34;mi&#34;&gt;110&lt;/span&gt;  &lt;span class=&#34;mf&#34;&gt;3.90&lt;/span&gt;  &lt;span class=&#34;mf&#34;&gt;2.620&lt;/span&gt;  &lt;span class=&#34;mf&#34;&gt;16.46&lt;/span&gt;   &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;   &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;     &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;     &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;      &lt;span class=&#34;n&#34;&gt;Mazda&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;RX4&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Wag&lt;/span&gt;  &lt;span class=&#34;mf&#34;&gt;21.0&lt;/span&gt;    &lt;span class=&#34;mi&#34;&gt;6&lt;/span&gt;  &lt;span class=&#34;mf&#34;&gt;160.0&lt;/span&gt;  &lt;span class=&#34;mi&#34;&gt;110&lt;/span&gt;  &lt;span class=&#34;mf&#34;&gt;3.90&lt;/span&gt;  &lt;span class=&#34;mf&#34;&gt;2.875&lt;/span&gt;  &lt;span class=&#34;mf&#34;&gt;17.02&lt;/span&gt;   &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;   &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;     &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;     &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;         &lt;span class=&#34;n&#34;&gt;Datsun&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;710&lt;/span&gt;  &lt;span class=&#34;mf&#34;&gt;22.8&lt;/span&gt;    &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;  &lt;span class=&#34;mf&#34;&gt;108.0&lt;/span&gt;   &lt;span class=&#34;mi&#34;&gt;93&lt;/span&gt;  &lt;span class=&#34;mf&#34;&gt;3.85&lt;/span&gt;  &lt;span class=&#34;mf&#34;&gt;2.320&lt;/span&gt;  &lt;span class=&#34;mf&#34;&gt;18.61&lt;/span&gt;   &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;   &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;     &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;     &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;     &lt;span class=&#34;n&#34;&gt;Hornet&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Drive&lt;/span&gt;  &lt;span class=&#34;mf&#34;&gt;21.4&lt;/span&gt;    &lt;span class=&#34;mi&#34;&gt;6&lt;/span&gt;  &lt;span class=&#34;mf&#34;&gt;258.0&lt;/span&gt;  &lt;span class=&#34;mi&#34;&gt;110&lt;/span&gt;  &lt;span class=&#34;mf&#34;&gt;3.08&lt;/span&gt;  &lt;span class=&#34;mf&#34;&gt;3.215&lt;/span&gt;  &lt;span class=&#34;mf&#34;&gt;19.44&lt;/span&gt;   &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;   &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;     &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;     &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;Hornet&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Sportabout&lt;/span&gt;  &lt;span class=&#34;mf&#34;&gt;18.7&lt;/span&gt;    &lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt;  &lt;span class=&#34;mf&#34;&gt;360.0&lt;/span&gt;  &lt;span class=&#34;mi&#34;&gt;175&lt;/span&gt;  &lt;span class=&#34;mf&#34;&gt;3.15&lt;/span&gt;  &lt;span class=&#34;mf&#34;&gt;3.440&lt;/span&gt;  &lt;span class=&#34;mf&#34;&gt;17.02&lt;/span&gt;   &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;   &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;     &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;     &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In ipython I can call the method and get a markdown table back as a string&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;mental&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lake&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;posts&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mental&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lake&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;to_markdown&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;|    | Unnamed: 0        |   mpg |   cyl |   disp |   hp |   drat |    wt |   qsec |   vs |   am |   gear |   carb |&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;|---:|:------------------|------:|------:|-------:|-----:|-------:|------:|-------:|-----:|-----:|-------:|-------:|&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;|  0 | Mazda RX4         |  21   |     6 |    160 |  110 |   3.9  | 2.62  |  16.46 |    0 |    1 |      4 |      4 |&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;|  1 | Mazda RX4 Wag     |  21   |     6 |    160 |  110 |   3.9  | 2.875 |  17.02 |    0 |    1 |      4 |      4 |&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;|  2 | Datsun 710        |  22.8 |     4 |    108 |   93 |   3.85 | 2.32  |  18.61 |    1 |    1 |      4 |      1 |&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;|  3 | Hornet 4 Drive    |  21.4 |     6 |    258 |  110 |   3.08 | 3.215 |  19.44 |    1 |    0 |      3 |      1 |&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;|  4 | Hornet Sportabout |  18.7 |     8 |    360 |  175 |   3.15 | 3.44  |  17.02 |    0 |    0 |      3 |      2 |&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can drop that string into a markdown file and using any reader that supports the rendering you&amp;rsquo;ll have a nicely formated table of example data in whatever report you&amp;rsquo;re making!&lt;/p&gt;&#xA;&lt;h1 id=&#34;bonus-method&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Bonus method&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;Just like markdown, you can export a dataframe to html with &lt;code&gt;df.to_html()&lt;/code&gt; and use that if it&amp;rsquo;s more appropriate for your use case:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#39;&amp;lt;table border=&amp;#34;1&amp;#34; class=&amp;#34;dataframe&amp;#34;&amp;gt;\n  &amp;lt;thead&amp;gt;\n    &amp;lt;tr style=&amp;#34;text-align: right;&amp;#34;&amp;gt;\n      &amp;lt;th&amp;gt;&amp;lt;/th&amp;gt;\n      &amp;lt;th&amp;gt;Unnamed: 0&amp;lt;/th&amp;gt;\n      &amp;lt;th&amp;gt;mpg&amp;lt;/th&amp;gt;\n      &amp;lt;th&amp;gt;cyl&amp;lt;/th&amp;gt;\n      &amp;lt;th&amp;gt;disp&amp;lt;/th&amp;gt;\n      &amp;lt;th&amp;gt;hp&amp;lt;/th&amp;gt;\n      &amp;lt;th&amp;gt;drat&amp;lt;/th&amp;gt;\n      &amp;lt;th&amp;gt;wt&amp;lt;/th&amp;gt;\n      &amp;lt;th&amp;gt;qsec&amp;lt;/th&amp;gt;\n      &amp;lt;th&amp;gt;vs&amp;lt;/th&amp;gt;\n      &amp;lt;th&amp;gt;am&amp;lt;/th&amp;gt;\n      &amp;lt;th&amp;gt;gear&amp;lt;/th&amp;gt;\n      &amp;lt;th&amp;gt;carb&amp;lt;/th&amp;gt;\n    &amp;lt;/tr&amp;gt;\n  &amp;lt;/thead&amp;gt;\n  &amp;lt;tbody&amp;gt;\n    &amp;lt;tr&amp;gt;\n      &amp;lt;th&amp;gt;0&amp;lt;/th&amp;gt;\n      &amp;lt;td&amp;gt;Mazda RX4&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;21.0&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;6&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;160.0&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;110&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;3.90&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;2.620&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;16.46&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;0&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;\n    &amp;lt;/tr&amp;gt;\n    &amp;lt;tr&amp;gt;\n      &amp;lt;th&amp;gt;1&amp;lt;/th&amp;gt;\n      &amp;lt;td&amp;gt;Mazda RX4 Wag&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;21.0&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;6&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;160.0&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;110&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;3.90&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;2.875&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;17.02&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;0&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;\n    &amp;lt;/tr&amp;gt;\n    &amp;lt;tr&amp;gt;\n      &amp;lt;th&amp;gt;2&amp;lt;/th&amp;gt;\n      &amp;lt;td&amp;gt;Datsun 710&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;22.8&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;108.0&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;93&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;3.85&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;2.320&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;18.61&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;\n    &amp;lt;/tr&amp;gt;\n    &amp;lt;tr&amp;gt;\n      &amp;lt;th&amp;gt;3&amp;lt;/th&amp;gt;\n      &amp;lt;td&amp;gt;Hornet 4 Drive&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;21.4&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;6&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;258.0&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;110&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;3.08&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;3.215&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;19.44&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;0&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;3&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;\n    &amp;lt;/tr&amp;gt;\n    &amp;lt;tr&amp;gt;\n      &amp;lt;th&amp;gt;4&amp;lt;/th&amp;gt;\n      &amp;lt;td&amp;gt;Hornet Sportabout&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;18.7&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;8&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;360.0&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;175&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;3.15&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;3.440&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;17.02&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;0&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;0&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;3&amp;lt;/td&amp;gt;\n      &amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;\n    &amp;lt;/tr&amp;gt;\n  &amp;lt;/tbody&amp;gt;\n&amp;lt;/table&amp;gt;&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;My blog will render that html into a nice table! (After removing new line characters)&lt;/p&gt;&#xA;&lt;table border=&#34;1&#34; class=&#34;dataframe&#34;&gt;  &lt;thead&gt;    &lt;tr style=&#34;text-align: right;&#34;&gt;      &lt;th&gt;Unnamed: 0&lt;/th&gt;      &lt;th&gt;mpg&lt;/th&gt;      &lt;th&gt;cyl&lt;/th&gt;      &lt;th&gt;disp&lt;/th&gt;      &lt;th&gt;hp&lt;/th&gt;      &lt;th&gt;drat&lt;/th&gt;      &lt;th&gt;wt&lt;/th&gt;      &lt;th&gt;qsec&lt;/th&gt;      &lt;th&gt;vs&lt;/th&gt;      &lt;th&gt;am&lt;/th&gt;      &lt;th&gt;gear&lt;/th&gt;      &lt;th&gt;carb&lt;/th&gt;    &lt;/tr&gt;  &lt;/thead&gt;  &lt;tbody&gt;    &lt;tr&gt;      &lt;td&gt;Mazda RX4&lt;/td&gt;      &lt;td&gt;21.0&lt;/td&gt;      &lt;td&gt;6&lt;/td&gt;      &lt;td&gt;160.0&lt;/td&gt;      &lt;td&gt;110&lt;/td&gt;      &lt;td&gt;3.90&lt;/td&gt;      &lt;td&gt;2.620&lt;/td&gt;      &lt;td&gt;16.46&lt;/td&gt;      &lt;td&gt;0&lt;/td&gt;      &lt;td&gt;1&lt;/td&gt;      &lt;td&gt;4&lt;/td&gt;      &lt;td&gt;4&lt;/td&gt;    &lt;/tr&gt;    &lt;tr&gt;      &lt;td&gt;Mazda RX4 Wag&lt;/td&gt;      &lt;td&gt;21.0&lt;/td&gt;      &lt;td&gt;6&lt;/td&gt;      &lt;td&gt;160.0&lt;/td&gt;      &lt;td&gt;110&lt;/td&gt;      &lt;td&gt;3.90&lt;/td&gt;      &lt;td&gt;2.875&lt;/td&gt;      &lt;td&gt;17.02&lt;/td&gt;      &lt;td&gt;0&lt;/td&gt;      &lt;td&gt;1&lt;/td&gt;      &lt;td&gt;4&lt;/td&gt;      &lt;td&gt;4&lt;/td&gt;    &lt;/tr&gt;    &lt;tr&gt;      &lt;td&gt;Datsun 710&lt;/td&gt;      &lt;td&gt;22.8&lt;/td&gt;      &lt;td&gt;4&lt;/td&gt;      &lt;td&gt;108.0&lt;/td&gt;      &lt;td&gt;93&lt;/td&gt;      &lt;td&gt;3.85&lt;/td&gt;      &lt;td&gt;2.320&lt;/td&gt;      &lt;td&gt;18.61&lt;/td&gt;      &lt;td&gt;1&lt;/td&gt;      &lt;td&gt;1&lt;/td&gt;      &lt;td&gt;4&lt;/td&gt;      &lt;td&gt;1&lt;/td&gt;    &lt;/tr&gt;    &lt;tr&gt;      &lt;td&gt;Hornet 4 Drive&lt;/td&gt;      &lt;td&gt;21.4&lt;/td&gt;      &lt;td&gt;6&lt;/td&gt;      &lt;td&gt;258.0&lt;/td&gt;      &lt;td&gt;110&lt;/td&gt;      &lt;td&gt;3.08&lt;/td&gt;      &lt;td&gt;3.215&lt;/td&gt;      &lt;td&gt;19.44&lt;/td&gt;      &lt;td&gt;1&lt;/td&gt;      &lt;td&gt;0&lt;/td&gt;      &lt;td&gt;3&lt;/td&gt;      &lt;td&gt;1&lt;/td&gt;    &lt;/tr&gt;    &lt;tr&gt;      &lt;td&gt;Hornet Sportabout&lt;/td&gt;      &lt;td&gt;18.7&lt;/td&gt;      &lt;td&gt;8&lt;/td&gt;      &lt;td&gt;360.0&lt;/td&gt;      &lt;td&gt;175&lt;/td&gt;      &lt;td&gt;3.15&lt;/td&gt;      &lt;td&gt;3.440&lt;/td&gt;      &lt;td&gt;17.02&lt;/td&gt;      &lt;td&gt;0&lt;/td&gt;      &lt;td&gt;0&lt;/td&gt;      &lt;td&gt;3&lt;/td&gt;      &lt;td&gt;2&lt;/td&gt;    &lt;/tr&gt;  &lt;/tbody&gt;&lt;/table&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Wish-List-With-Fastapi</title>
    <id>https://pype.dev/wish-list-with-fastapi/</id>
    <updated>2022-05-06T00:00:00Z</updated>
    <published>2022-05-06T00:00:00Z</published>
    <link href="https://pype.dev/wish-list-with-fastapi/" rel="alternate" type="text/html"></link>
    <summary type="text">Amazon has crossed the line with me just one too many times now so we are looking to drop them like every other Big Tech provider....</summary>
    <content type="html">&lt;p&gt;Amazon has crossed the line with me just one too many times now so we are looking to drop them like every other Big Tech provider&amp;hellip;.&lt;/p&gt;&#xA;&lt;p&gt;However, one key feature of Amazon that has been so useful for us is Lists&amp;hellip; We can just maintain a list for each of us and then family members can login anytime and check it out&amp;hellip;&#xA;This really alleviates any last minute gift idea stress right before a birthday or something.&lt;/p&gt;&#xA;&lt;p&gt;So I need a nice gift list service but I don&amp;rsquo;t want to be locked into one company (like a Target registry or something) and I&amp;rsquo;d like to host it myself&lt;/p&gt;&#xA;&lt;p&gt;The internets had a few options but nothing looked/felt like I wanted to I decided to build my own.&lt;/p&gt;&#xA;&lt;h1 id=&#34;the-frontend&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Frontend&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;&lt;strong&gt;I have no idea how to do front end so stay tuned&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;h1 id=&#34;the-backend&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Backend&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;FastAPI for the win on this one&amp;hellip; I followed a few examples online and what I was able to build in just a few minutes is pretty impressive thanks to the design of FastAPI.&lt;/p&gt;&#xA;&lt;p&gt;Some key features are:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Auto doc generation&lt;/li&gt;&#xA;&lt;li&gt;Required typing (which makes #1 possible)&lt;/li&gt;&#xA;&lt;li&gt;Built-in api testing in the browser&lt;/li&gt;&#xA;&lt;li&gt;Easy integration with sqlalchemy&lt;/li&gt;&#xA;&lt;li&gt;Development time so short you won&amp;rsquo;t be done with your coffee before having something up and running!&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;database&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Database&lt;/span&gt; &lt;a href=&#34;#database&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Starting with a simple &lt;code&gt;database.py&lt;/code&gt; we can create a sqlalchemy session with a base model with about 7 lines of code&amp;hellip;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;sqlalchemy&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;create_engine&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;sqlalchemy.ext.declarative&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;declarative_base&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;sqlalchemy.orm&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sessionmaker&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;SQLALCHEMY_DATABASE_URL&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;sqlite:///wishes.sqlite3&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;engine&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;create_engine&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SQLALCHEMY_DATABASE_URL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;SessionLocal&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sessionmaker&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;autocommit&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;autoflush&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;bind&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;engine&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;Base&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;declarative_base&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;model&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Model&lt;/span&gt; &lt;a href=&#34;#model&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;For my wish list I needed just a simple table:&lt;/p&gt;&#xA;&lt;table&gt;&#xA;&lt;thead&gt;&#xA;&lt;tr&gt;&#xA;&lt;th style=&#34;text-align:right&#34;&gt;id&lt;/th&gt;&#xA;&lt;th style=&#34;text-align:left&#34;&gt;person&lt;/th&gt;&#xA;&lt;th style=&#34;text-align:left&#34;&gt;item&lt;/th&gt;&#xA;&lt;th style=&#34;text-align:left&#34;&gt;link&lt;/th&gt;&#xA;&lt;th style=&#34;text-align:left&#34;&gt;purchased&lt;/th&gt;&#xA;&lt;th style=&#34;text-align:left&#34;&gt;purchased_by&lt;/th&gt;&#xA;&lt;th style=&#34;text-align:left&#34;&gt;date_added&lt;/th&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/thead&gt;&#xA;&lt;tbody&gt;&#xA;&lt;tr&gt;&#xA;&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;&#xA;&lt;td style=&#34;text-align:left&#34;&gt;pypeaday&lt;/td&gt;&#xA;&lt;td style=&#34;text-align:left&#34;&gt;A sweet item&lt;/td&gt;&#xA;&lt;td style=&#34;text-align:left&#34;&gt;&lt;a href=&#34;http://www.mystore.store&#34;&gt;www.mystore.store&lt;/a&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;text-align:left&#34;&gt;False&lt;/td&gt;&#xA;&lt;td style=&#34;text-align:left&#34;&gt;dad&lt;/td&gt;&#xA;&lt;td style=&#34;text-align:left&#34;&gt;2022-05-05 21:55:09&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td style=&#34;text-align:right&#34;&gt;2&lt;/td&gt;&#xA;&lt;td style=&#34;text-align:left&#34;&gt;pypeaday&lt;/td&gt;&#xA;&lt;td style=&#34;text-align:left&#34;&gt;A bitter item&lt;/td&gt;&#xA;&lt;td style=&#34;text-align:left&#34;&gt;&lt;a href=&#34;http://www.bitterstore.com&#34;&gt;www.bitterstore.com&lt;/a&gt;&lt;/td&gt;&#xA;&lt;td style=&#34;text-align:left&#34;&gt;True&lt;/td&gt;&#xA;&lt;td style=&#34;text-align:left&#34;&gt;Mrs. pypeaday&lt;/td&gt;&#xA;&lt;td style=&#34;text-align:left&#34;&gt;2022-05-06 06:55:54&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;The table is simple enough&amp;hellip; A unique key, the person who the wish belongs to, the item (or wish), a link to the item, whether it&amp;rsquo;s been purchased or not and by whom, and the date it was added.&lt;/p&gt;&#xA;&lt;p&gt;To make this model with sqlalchemy we can make a &lt;code&gt;model.py&lt;/code&gt; like so:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;database&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Base&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;sqlalchemy.schema&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Column&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;sqlalchemy.types&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Boolean&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Integer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Text&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Wishes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Base&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;__tablename__&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Wishes&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;id&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Column&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Integer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;primary_key&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;person&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Column&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;20&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;item&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Column&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;link&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Column&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;purchased&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Column&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Boolean&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;purchased_by&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Column&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;90&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;date_added&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Column&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;15&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;schema&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Schema&lt;/span&gt; &lt;a href=&#34;#schema&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;One of the best things about FastAPI is trivial integration with pydantic.&#xA;We can define a schema to ensure any data posted is not missing anything!&lt;/p&gt;&#xA;&lt;p&gt;Make a &lt;code&gt;schema.py&lt;/code&gt; with the following:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;pydantic&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;BaseModel&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;time&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;typing&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Optional&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;wish_schema&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;BaseModel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;person&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;item&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;link&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;purchased&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;bool&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;purchased_by&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Optional&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;date_added&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Optional&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;strftime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;%Y-%m-&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;%d&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; %H:%M:%S&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;localtime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Config&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;orm_mode&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;patch_schema&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;BaseModel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;purchased&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;bool&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;purchased_by&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Optional&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Config&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;orm_mode&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I have 2 schemas - one for a &lt;code&gt;wish&lt;/code&gt; which you&amp;rsquo;ll see down below is used to validate any &lt;code&gt;post&lt;/code&gt; requests.&lt;/p&gt;&#xA;&lt;p&gt;To simplify things for me I made another schema, &lt;code&gt;patch_schema&lt;/code&gt; which I use for the route that updates the table (ie. marking an existing wish as purchased)&lt;/p&gt;&#xA;&lt;h2 id=&#34;session&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Session&lt;/span&gt; &lt;a href=&#34;#session&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;One of the last things we need is a Session&lt;/p&gt;&#xA;&lt;p&gt;So make a &lt;code&gt;session.py&lt;/code&gt;&amp;hellip;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;database&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SessionLocal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;engine&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;model&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Base&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;metadata&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;create_all&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bind&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;engine&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;create_get_session&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;db&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SessionLocal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;yield&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;finally&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;close&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Our routes will depend on this &lt;code&gt;create_get_session&lt;/code&gt; function that will yield a &lt;code&gt;db&lt;/code&gt; object through which we&amp;rsquo;ll udpate our database&lt;/p&gt;&#xA;&lt;h1 id=&#34;ok-just-do-it-already&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Ok just do it already!&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;So our &lt;code&gt;main.py&lt;/code&gt; will have a few routes in it&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;What do we want to support?&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Getting all wishes&lt;/li&gt;&#xA;&lt;li&gt;Getting a specific wish&lt;/li&gt;&#xA;&lt;li&gt;Updating a specific wish&lt;/li&gt;&#xA;&lt;li&gt;Deleting a wish&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;I think the script is fairly self explanatory but here&amp;rsquo;s a few notes&amp;hellip;&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;We decorate each function with &lt;code&gt;@app.&amp;lt;method&amp;gt;&lt;/code&gt; and define &lt;code&gt;response_model&lt;/code&gt; as well as &lt;code&gt;status_code&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;The functions are defined with &lt;code&gt;async&lt;/code&gt; (this was my first exposure to this so I can&amp;rsquo;t go in depth on it yet)&lt;/li&gt;&#xA;&lt;li&gt;The functions all take a &lt;code&gt;db&lt;/code&gt; which is from &lt;code&gt;session.py&lt;/code&gt; and that &lt;code&gt;db&lt;/code&gt; depends on the &lt;code&gt;create_get_session&lt;/code&gt; function&lt;/li&gt;&#xA;&lt;li&gt;If the db is being updtes then we type the object used for the update with the appropriate schema (either &lt;code&gt;wish_schema&lt;/code&gt; or &lt;code&gt;patch_schema&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;From there we&amp;rsquo;re in true python-land where you can basically guess the methods on &lt;code&gt;db&lt;/code&gt; and you&amp;rsquo;d probably be right&amp;hellip; (like &lt;code&gt;query&lt;/code&gt;, &lt;code&gt;upddate&lt;/code&gt;, &lt;code&gt;delete&lt;/code&gt; etc.)&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;fastapi&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FastAPI&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Depends&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;HTTPException&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;sqlalchemy.orm&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Session&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;typing&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;List&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;model&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Wishes&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;schema&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;wish_schema&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;patch_schema&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;session&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;create_get_session&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;app&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FastAPI&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@app.get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;read_root&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;server is up!&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@app.get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/wishes&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;response_model&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;List&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;wish_schema&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;status_code&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;200&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;async&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;read_wishes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Session&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Depends&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;create_get_session&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;wishes&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;query&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Wishes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;all&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;wishes&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@app.post&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/wishes&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;response_model&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;wish_schema&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;status_code&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;201&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;async&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;add_wish&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;wish&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;wish_schema&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Session&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Depends&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;create_get_session&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;new_wish&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Wishes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;person&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;wish&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;person&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;item&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;wish&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;item&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;link&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;wish&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;link&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;purchased&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;wish&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;purchased&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;purchased_by&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;wish&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;purchased_by&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;date_added&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;wish&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;date_added&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;new_wish&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;commit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;new_wish&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@app.get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/wishes/&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{id}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;response_model&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;wish_schema&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;status_code&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;200&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;async&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;get_wish&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Session&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Depends&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;create_get_session&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;wish&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;query&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Wishes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;wish&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@app.patch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/wishes/&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{id}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;response_model&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;wish_schema&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;status_code&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;200&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;async&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;update_wish&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;patch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;patch_schema&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Session&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Depends&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;create_get_session&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;db_wish&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;query&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Wishes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;db_wish&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;purchased&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;patch&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;purchased&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;db_wish&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;purchased_by&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;patch&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;purchased_by&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;commit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;refresh&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;db_wish&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;db_wish&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@app.delete&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/wishes/&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{id}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;status_code&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;200&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;async&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;delete_wish&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Session&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Depends&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;create_get_session&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;db_wish&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;query&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Wishes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;db_wish&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;HTTPException&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status_code&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;404&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;detail&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Wish id does not exist&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;delete&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;db_wish&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;commit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;my-code&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;My Code&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;You can find my repo &lt;a href=&#34;https://github.com/nicpayne713/wish-lists&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;ll plan to update and maintain for as long as I use it&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Git-Bisect</title>
    <id>https://pype.dev/git-bisect/</id>
    <updated>2022-05-03T00:00:00Z</updated>
    <published>2022-05-03T00:00:00Z</published>
    <link href="https://pype.dev/git-bisect/" rel="alternate" type="text/html"></link>
    <summary type="text">I try to commit a lot, and I also try to write useful tests appropriate for the scope of work I&#39;m focusing on, but sometimes I drop the ball...</summary>
    <content type="html">&lt;p&gt;I try to commit a lot, and I also try to write useful tests appropriate for the scope of work I&amp;rsquo;m focusing on, but sometimes I drop the ball&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;Whether by laziness, ignorance, or accepted tech debt I don&amp;rsquo;t always code perfectly and recently I was dozens of commits into a new feature before realizing I broke something along the way that none of my tests caught&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;Before today I would&amp;rsquo;ve manually reviewed every commit to see if something obvious slipped by me (talk about a time suck 😩)&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;There must be a better way&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;h1 id=&#34;bisect&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Bisect?&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;&lt;code&gt;git bisect&lt;/code&gt; is the magic sauce for this exact problem&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;You essentially create a range of commits to consider and let &lt;code&gt;git bisect&lt;/code&gt; guide you through them in a manner akin to Newton&amp;rsquo;s method for finding the root of a continuous function.&lt;/p&gt;&#xA;&lt;h1 id=&#34;how-to-do-it&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;How to do it?&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;Start with &lt;code&gt;git bisect start&lt;/code&gt; and then choose the first &lt;code&gt;good&lt;/code&gt; commit (ie. a commit you know the bug isn&amp;rsquo;t present in)&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sandbox   bisect-post   ×1 via   v3.8.11&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;sandbox&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;  on  &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;us-east-1&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ git bisect start&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sandbox   bisect-post &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;BISECTING&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;   ×1 via   v3.8.11&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;sandbox&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;  on  &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;us-east-1&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ git bisect good 655332b&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bisect-post  HEAD         main         ORIG_HEAD&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;5b31e1e  -- &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;HEAD&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;    add successful print &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;52&lt;/span&gt; seconds ago&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;308247b  -- &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;HEAD^&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;   init another loop &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;77&lt;/span&gt; seconds ago&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;4555c59  -- &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;HEAD^^&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;  introduce bug &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2&lt;/span&gt; minutes ago&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;9cf6d55  -- &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;HEAD~3&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;  add successful loop &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;3&lt;/span&gt; minutes ago&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bcb41c3  -- &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;HEAD~4&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;  change x to &lt;span class=&#34;m&#34;&gt;10&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;4&lt;/span&gt; minutes ago&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;3c34aac  -- &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;HEAD~5&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;  init x to &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;4&lt;/span&gt; minutes ago&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;12e53bd  -- &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;HEAD~6&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;  print cwd &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;4&lt;/span&gt; minutes ago&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;655332b  -- &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;HEAD~7&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;  add example.py &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;10&lt;/span&gt; minutes ago&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# &amp;lt;- I want to start at this commit&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;59e0048  -- &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;HEAD~8&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;  gitignore &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;23&lt;/span&gt; hours ago&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;fb9e1fb  -- &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;HEAD~9&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;  add reqs &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;23&lt;/span&gt; hours ago&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sandbox   bisect-post &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;BISECTING&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;   ×1 via   v3.8.11&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;sandbox&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;  on  &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;us-east-1&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ git bisect bad 5b31e1e&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bisect-post                                                ORIG_HEAD&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;HEAD                                                       refs/bisect/good-655332b6c384934c2c00c3d4aba3011ccc1e5b57&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;5b31e1e  -- &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;HEAD&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;    add successful print &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;5&lt;/span&gt; minutes ago&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# &amp;lt;- I start here with the &amp;#34;bad&amp;#34; commit&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;308247b  -- &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;HEAD^&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;   init another loop &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;6&lt;/span&gt; minutes ago&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;4555c59  -- &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;HEAD^^&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;  introduce bug &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;6&lt;/span&gt; minutes ago&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;9cf6d55  -- &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;HEAD~3&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;  add successful loop &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;7&lt;/span&gt; minutes ago&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bcb41c3  -- &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;HEAD~4&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;  change x to &lt;span class=&#34;m&#34;&gt;10&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;8&lt;/span&gt; minutes ago&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;3c34aac  -- &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;HEAD~5&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;  init x to &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;9&lt;/span&gt; minutes ago&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;12e53bd  -- &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;HEAD~6&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;  print cwd &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;9&lt;/span&gt; minutes ago&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;655332b  -- &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;HEAD~7&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;  add example.py &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;14&lt;/span&gt; minutes ago&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;59e0048  -- &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;HEAD~8&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;  gitignore &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;23&lt;/span&gt; hours ago&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;fb9e1fb  -- &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;HEAD~9&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;  add reqs &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;23&lt;/span&gt; hours ago&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;After starting bisect with a &amp;ldquo;good&amp;rdquo; start commit and a &amp;ldquo;bad&amp;rdquo; ending commit we can let git to it&amp;rsquo;s thing!&lt;/p&gt;&#xA;&lt;p&gt;Git checksout a commit somewhere about halfway between the good and bad commit so you can see if your bug is there or not.&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sandbox   bisect-post &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;BISECTING&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;   ×1 via   v3.8.11&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;sandbox&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;  on  &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;us-east-1&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ git bisect bad 5b31e1e&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Bisecting: &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt; revisions left to &lt;span class=&#34;nb&#34;&gt;test&lt;/span&gt; after this &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;roughly &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt; steps&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;bcb41c3854e343eade85353683f2c1c4ddde4e04&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; change x to &lt;span class=&#34;m&#34;&gt;10&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sandbox   HEAD &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;bcb41c38&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;BISECTING&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;   ×1 via   v3.8.11&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;sandbox&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;  on  &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;us-east-1&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In my example here I have a python script with some loops and print statements - they aren&amp;rsquo;t really relevant, I just wanted an easy to follow git history.&lt;/p&gt;&#xA;&lt;p&gt;So I check to see if the bug is present or not either by running/writing tests or replicating the bug somehow.&lt;/p&gt;&#xA;&lt;p&gt;In this session commit &lt;code&gt;bcb41c38&lt;/code&gt; is actually just fine, so I do &lt;code&gt;git bisect good&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sandbox   HEAD &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;bcb41c38&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;BISECTING&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;   ×1 via   v3.8.11&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;sandbox&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;  on  &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;us-east-1&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ git bisect good&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Bisecting: &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; revision left to &lt;span class=&#34;nb&#34;&gt;test&lt;/span&gt; after this &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;roughly &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; step&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;4555c5979268dff6c475365fdc5ce1d4a12bd820&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; introduce bug&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And we see that git moves on to checkout another commit&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;In this case the next commit is the one where I introduced a bug&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;git bisect bad&lt;/code&gt; then gives me:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sandbox   HEAD &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;4555c597&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;BISECTING&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;   ×1 via   v3.8.11&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;sandbox&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;  on  &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;us-east-1&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ git bisect bad&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Bisecting: &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; revisions left to &lt;span class=&#34;nb&#34;&gt;test&lt;/span&gt; after this &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;roughly &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; steps&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;9cf6d55301560c51e2f55404d0d80b1f1e22a33d&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; add successful loop&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;At &lt;code&gt;4555c597&lt;/code&gt; the script works as expected so one more &lt;code&gt;git bisect good&lt;/code&gt; yields&amp;hellip;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sandbox   HEAD &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;9cf6d553&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;BISECTING&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;   ×1 via   v3.8.11&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;sandbox&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;  on  &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;us-east-1&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ git bisect good&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;4555c5979268dff6c475365fdc5ce1d4a12bd820 is the first bad commit&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;commit 4555c5979268dff6c475365fdc5ce1d4a12bd820&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Author: &lt;span class=&#34;c1&#34;&gt;########################### &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Date:   Tue May &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt; 09:00:00 &lt;span class=&#34;m&#34;&gt;2022&lt;/span&gt; -0500&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    introduce bug&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; example.py &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt; +-&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; file changed, &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; insertion&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;+&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;, &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; deletion&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;-&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;what-happened&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;What happened?&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;Git sliced up a range of commits based on me saying of the next one was good or bad and localized the commit that introduced a bug into my workflow!&lt;/p&gt;&#xA;&lt;p&gt;I didn&amp;rsquo;t have to manually review commits, click through logs, etc&amp;hellip; I just let git checkout relevant commits and I ran whatever was appropriate for reproducing the bug to learn when it was comitted!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Pandas-String-Contains</title>
    <id>https://pype.dev/pandas-string-contains/</id>
    <updated>2022-05-02T00:00:00Z</updated>
    <published>2022-05-02T00:00:00Z</published>
    <link href="https://pype.dev/pandas-string-contains/" rel="alternate" type="text/html"></link>
    <summary type="text">accepts regular expressions and this is turned on by __!</summary>
    <content type="html">&lt;h1 id=&#34;tl-dr&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;TL;DR&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;&lt;code&gt;pandas.Series.str.contains&lt;/code&gt; accepts regular expressions and this is turned on by &lt;strong&gt;default&lt;/strong&gt;!&lt;/p&gt;&#xA;&lt;h1 id=&#34;use-case&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Use case&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;We often need to filter pandas DataFrames based on several string values in a Series.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Notice that sweet pyflyby import 😁!&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;DataFrame&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;A&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;string1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;string2&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;string3&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]})&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PYFLYBY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;pandas&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;pd&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         &lt;span class=&#34;n&#34;&gt;A&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;string1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;string2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;string3&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;contains&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;contains&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;2&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         &lt;span class=&#34;n&#34;&gt;A&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;string1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;string2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And this isn&amp;rsquo;t the worst thing in the world, especially for such a tiny example&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;But what if we had dozens or more values to filter on?&lt;/p&gt;&#xA;&lt;p&gt;Then it looks so much nicer to create an iterable of the values we want to filter on and join them with an apropriate regex operator (in this case &lt;code&gt;|&lt;/code&gt; for &lt;em&gt;inclusive or&lt;/em&gt;)&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vals&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;2&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# iterable with whatever is appropriate for your use case&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;contains&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;|&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;join&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vals&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;regex&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         &lt;span class=&#34;n&#34;&gt;A&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;string1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;string2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;fin&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Fin&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;This is a super nice and concise way to do the kind of filtering my team does on a daily basis!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Unpack-Anywhere-With-Star</title>
    <id>https://pype.dev/unpack-anywhere-with-star/</id>
    <updated>2022-04-24T00:00:00Z</updated>
    <published>2022-04-24T00:00:00Z</published>
    <link href="https://pype.dev/unpack-anywhere-with-star/" rel="alternate" type="text/html"></link>
    <summary type="text">Unpacking iterables in python with is a pretty handy trick for writing code that is just a tiny bit more pythonic than not.</summary>
    <content type="html">&lt;p&gt;Unpacking iterables in python with &lt;code&gt;*&lt;/code&gt; is a pretty handy trick for writing code that is just a tiny bit more pythonic than not.&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;arr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Tuple&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Union&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;arr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# the * unpacks the tuple into the individual elements&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;arr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;z&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alphas&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;arr&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# x = 1, y = 2, z = 3&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# alphas = [ &amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39; ]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But &lt;a href=&#34;https://twitter.com/nedbat&#34;&gt;@Ned Batchelder&lt;/a&gt; showed me via Twitter than you can arbitrarily unpack arguments based on position - it doesn&amp;rsquo;t have to be done at the beginning or the end!&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mixed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;arr&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# x = 1, y = 2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# mixed = [3, &amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# alpha = &amp;#39;c&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I&amp;rsquo;m not entirely sure when I&amp;rsquo;ll need this but it definitley shows me another example of how flexible python is!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Htop</title>
    <id>https://pype.dev/htop/</id>
    <updated>2022-04-24T00:00:00Z</updated>
    <published>2022-04-24T00:00:00Z</published>
    <link href="https://pype.dev/htop/" rel="alternate" type="text/html"></link>
    <summary type="text">is a common command line tool for seeing interactive output of your system resource utilization, running processes, etc.</summary>
    <content type="html">&lt;p&gt;&lt;code&gt;htop&lt;/code&gt; is a common command line tool for seeing interactive output of your system resource utilization, running processes, etc.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve always been super confused about htop showing seemingly the same process several times though&amp;hellip;&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-fix&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Fix…&lt;/span&gt; &lt;a href=&#34;#the-fix&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Just hit &lt;code&gt;H&lt;/code&gt;&amp;hellip;. makes the view a lot nicer 😀&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Pipx</title>
    <id>https://pype.dev/pipx/</id>
    <updated>2022-04-22T00:00:00Z</updated>
    <published>2022-04-22T00:00:00Z</published>
    <link href="https://pype.dev/pipx/" rel="alternate" type="text/html"></link>
    <summary type="text">is a tool I&#39;ve been using to solve a few problems of mine...</summary>
    <content type="html">&lt;p&gt;&lt;code&gt;pipx&lt;/code&gt; is a tool I&amp;rsquo;ve been using to solve a few problems of mine&amp;hellip;&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;pinning formatting tools like &lt;code&gt;black&lt;/code&gt;, &lt;code&gt;flake8&lt;/code&gt;, &lt;code&gt;isort&lt;/code&gt;, etc. to the same version for all my projects&lt;/li&gt;&#xA;&lt;li&gt;keeping virtual environments clean of things like &lt;code&gt;cookiecutter&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;python utilities I want system wide but not in the global environment, like &lt;code&gt;visidata&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;what-is-it&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;What is it?&lt;/span&gt; &lt;a href=&#34;#what-is-it&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;&lt;code&gt;pip&lt;/code&gt; itself is just a package manager like &lt;code&gt;homebrew&lt;/code&gt;, &lt;code&gt;apt&lt;/code&gt;, etc. But it is tied to a python environment.&#xA;If you aren&amp;rsquo;t using a virtual environment then &lt;code&gt;pip&lt;/code&gt; will operate inside the global installation of python.&lt;/p&gt;&#xA;&lt;p&gt;Operating within that environment has burned me several times and now I have a strict virtual environment usage policy.&lt;/p&gt;&#xA;&lt;p&gt;But there are still things I don&amp;rsquo;t want to have to put in every virtual environment - enter &lt;code&gt;pipx&lt;/code&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-s-it-do&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;What’s it do?&lt;/span&gt; &lt;a href=&#34;#what-s-it-do&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;When you &lt;code&gt;pipx install {package}&lt;/code&gt; a stand alone virtual environment gets created (by default in &lt;code&gt;~/.local/pipx/venvs&lt;/code&gt;).&#xA;THen you can install extra dependencies with &lt;code&gt;pipx inject {package} {dependency}&lt;/code&gt;&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;ex. After &lt;code&gt;pipx install visidata&lt;/code&gt; in order to open Excel files you need to &lt;code&gt;pipx inject visidata xlrd&lt;/code&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;In the example with &lt;code&gt;visidata&lt;/code&gt;, I can then use it anywhere, in any project, without re-installing with &lt;code&gt;pip&lt;/code&gt; in every env.&lt;/p&gt;&#xA;&lt;p&gt;Also for the formatting tools - I configure vim to run the &lt;code&gt;pipx&lt;/code&gt; versions of them on save - this way I don&amp;rsquo;t have to put them in every project&amp;rsquo;s virtual environment!&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-about-pip&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;What about pip?&lt;/span&gt; &lt;a href=&#34;#what-about-pip&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;So obviously you can&amp;rsquo;t &lt;code&gt;pipx&lt;/code&gt; everything, nor do you want to.&#xA;I see it as a safe and better alternative to global package installation.&lt;/p&gt;&#xA;&lt;p&gt;How can you then be sure that you never &lt;code&gt;pip install&lt;/code&gt; into the global env?&lt;/p&gt;&#xA;&lt;p&gt;Add &lt;code&gt;require-virtualenv = True&lt;/code&gt; to your &lt;code&gt;pip.conf&lt;/code&gt; and you&amp;rsquo;re good to go!&lt;/p&gt;&#xA;&lt;p&gt;With that set, if you try to &lt;code&gt;pip install pandas&lt;/code&gt; into the global env you&amp;rsquo;ll get a message like this:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;~ on  &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;us-east-1&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;  NO PYTHON VENV SET&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ pip install pandas&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ERROR: Could not find an activated virtualenv &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;required&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;end&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;End&lt;/span&gt; &lt;a href=&#34;#end&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Disable your system &lt;code&gt;pip&lt;/code&gt; to keep your base python safe&lt;/li&gt;&#xA;&lt;li&gt;Use &lt;code&gt;pipx&lt;/code&gt; for tools you want available everywhere or don&amp;rsquo;t have to need in a virtual environment!&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Fx-Json</title>
    <id>https://pype.dev/fx-json/</id>
    <updated>2022-04-19T00:00:00Z</updated>
    <published>2022-04-19T00:00:00Z</published>
    <link href="https://pype.dev/fx-json/" rel="alternate" type="text/html"></link>
    <summary type="text">fx is an interactaive JSON viewer for the terminal.</summary>
    <content type="html">&lt;p&gt;&lt;a href=&#34;https://github.com/antonmedv/fx&#34;&gt;fx&lt;/a&gt; is an interactaive JSON viewer for the terminal.&lt;/p&gt;&#xA;&lt;p&gt;It&amp;rsquo;s a simple tool built with Charmcli&amp;rsquo;s Bubble Tea.&lt;/p&gt;&#xA;&lt;h2 id=&#34;installation&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Installation&lt;/span&gt; &lt;a href=&#34;#installation&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;The installation with go was broken for me - both via the link and direct from the repo.&#xA;Now I&amp;rsquo;m not a gopher so I don&amp;rsquo;t really know how to fix that.&lt;/p&gt;&#xA;&lt;p&gt;Luckily &lt;code&gt;npm install fx&lt;/code&gt; also works and got me what I needed!&lt;/p&gt;&#xA;&lt;h2 id=&#34;usage&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Usage&lt;/span&gt; &lt;a href=&#34;#usage&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Usage is simple&amp;hellip; &lt;code&gt;fx &amp;lt;json file&amp;gt;&lt;/code&gt;.&#xA;The Github has a few other ways such as &lt;code&gt;curl ... | fx&lt;/code&gt; etc.&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Jellyfin-Media-Players</title>
    <id>https://pype.dev/jellyfin-media-players/</id>
    <updated>2022-04-17T00:00:00Z</updated>
    <published>2022-04-17T00:00:00Z</published>
    <link href="https://pype.dev/jellyfin-media-players/" rel="alternate" type="text/html"></link>
    <summary type="text">I use Jellyfin at home for serving up most of our media - movies and shows etc.</summary>
    <content type="html">&lt;p&gt;I use Jellyfin at home for serving up most of our media - movies and shows etc.&lt;/p&gt;&#xA;&lt;p&gt;My dream is to have a GPU capable of transcoding any and all of our media for smooth playback on any device&amp;hellip;&#xA;Now, I thought I&amp;rsquo;d have that by now with my Nvidia Quadro P400 however I have issues left and right with 4k content.&lt;/p&gt;&#xA;&lt;p&gt;What can I do to still use Jellyfin but get smooth playback?&lt;/p&gt;&#xA;&lt;p&gt;THe first answer is figure out why I suck with GPUs, but pausing that there&amp;rsquo;s shorter solutions -&amp;gt; namely, use a media player that&amp;rsquo;s compatabile with the encoded content!&lt;/p&gt;&#xA;&lt;h2 id=&#34;vlc&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;VLC&lt;/span&gt; &lt;a href=&#34;#vlc&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I&amp;rsquo;ll keep this one short - VLC is great and if you don&amp;rsquo;t need a netflix like experience, I&amp;rsquo;d recommend just using it to browse your network drives and play whatever you have&lt;/p&gt;&#xA;&lt;h2 id=&#34;jellyfin-web-player&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Jellyfin Web Player&lt;/span&gt; &lt;a href=&#34;#jellyfin-web-player&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;This is the reason I&amp;rsquo;m writing this post&amp;hellip; the web player is great but not everything is supported on all devices&lt;/p&gt;&#xA;&lt;h2 id=&#34;jellyfin-mpv-shim&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Jellyfin MPV Shim&lt;/span&gt; &lt;a href=&#34;#jellyfin-mpv-shim&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;This cross-platform cast client is my answer now.&#xA;You can find the project &lt;a href=&#34;https://github.com/jellyfin/jellyfin-mpv-shim/blob/master/README.md#linux-installation&#34;&gt;here&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;The installation instrauctions are super straightforward for Windows, Mac OS, or Linux.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;m on Linux and so my install went like this:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo apt update&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo apt install mpv &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pipx install jellyfin-mpv-shim&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pipx inject jellyfin-mpv-shim pystray&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;#profit&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I used &lt;code&gt;pipx&lt;/code&gt; to install the player as I prefer it for stand alone utilities over pip installing anything globally.&lt;/p&gt;&#xA;&lt;p&gt;Afer that I just start the player at the terminal with &lt;code&gt;jellyfin-mpv-shim&lt;/code&gt;&#xA;Then in the web browser I can cast my content to the player and bypass the web player (and thus solve much of my transcoding issues) trivially!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Typeddict</title>
    <id>https://pype.dev/typeddict/</id>
    <updated>2022-04-15T00:00:00Z</updated>
    <published>2022-04-15T00:00:00Z</published>
    <link href="https://pype.dev/typeddict/" rel="alternate" type="text/html"></link>
    <summary type="text">Type hinting has helped me write code almost as much, if not more, than unit testing.</summary>
    <content type="html">&lt;p&gt;Type hinting has helped me write code almost as much, if not more, than unit testing.&lt;/p&gt;&#xA;&lt;p&gt;One thing I love is that with complete type hinting you get a lot more out of your LSP.&#xA;Typing dictionaries can be tricky and I recently learned about &lt;code&gt;TypedDict&lt;/code&gt; to do exactly what I needed!&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-problem&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Problem&lt;/span&gt; &lt;a href=&#34;#the-problem&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;It might not be straight up obvious what the problem is, especially if you don&amp;rsquo;t utilize tools like &lt;code&gt;mypy&lt;/code&gt; or &lt;code&gt;flake8&lt;/code&gt; in your development.&lt;/p&gt;&#xA;&lt;p&gt;My handy-dandy &lt;code&gt;nvim-lsp&lt;/code&gt; gives me a lot of feedback when I&amp;rsquo;m coding and it&amp;rsquo;s immensely helpful.&lt;/p&gt;&#xA;&lt;p&gt;So with the LSP giving me constant feedback here&amp;rsquo;s the issue:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;typing&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;List&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Union&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;my_dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Union&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;List&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;key_1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;val_1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;key_2&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;ls_1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;ls_2&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;my_dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;key_2&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;With the above script you&amp;rsquo;ll get an annoying warning about using &lt;code&gt;pop&lt;/code&gt; on &lt;code&gt;key_2&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/typed-dict-warning.png&#34; alt=&#34;typeddict&#34; title=&#34;Warning in TypedDict&#34; /&gt;&#xA;&lt;h2 id=&#34;the-solution&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Solution&lt;/span&gt; &lt;a href=&#34;#the-solution&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Maybe you can stomach getting yelled at by your LSP but I like complete silence if at all possible.&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;TypedDict&lt;/code&gt;  was the saving grace.&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;typing&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TypedDict&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;MyDict&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TypedDict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;MyDict&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;key_1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;key_2&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;List&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]})&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;my_typed_dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;MyDict&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;key_1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;val_1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;key_2&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;ls_1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;ls_2&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;my_typed_dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;key_2&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/typed-dict.png&#34; alt=&#34;typeddict&#34; title=&#34;A TypedDict&#34; /&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;I was able to import TypedDict from typing, mypy_extensions, and typing_extensions&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;With &lt;code&gt;TypedDict&lt;/code&gt; you define your custom type, match the first argument to &lt;code&gt;TypedDict&lt;/code&gt; with the name of the variable (idk why), then type hint each key you expect in the dict!&#xA;It&amp;rsquo;s super easy and I think puts you into a position of being extremely explicit with your dictionary variables.&#xA;This isn&amp;rsquo;t always desired or appropriate but in most of my use cases it is.&lt;/p&gt;&#xA;&lt;h2 id=&#34;rtfm&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;RTFM&lt;/span&gt; &lt;a href=&#34;#rtfm&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;There&amp;rsquo;s other implementation of &lt;code&gt;TypedDict&lt;/code&gt; and while writing this I saw that most of the docs define a &lt;code&gt;class&lt;/code&gt; for the type like this:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;typing&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TypedDict&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;MyDict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;TypedDict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;key_1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;key_2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;List&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;my_dict&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;MyDict&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;key_1&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;val_1&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;key_2&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;ls_1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;ls_2&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href=&#34;https://peps.python.org/pep-0589/&#34;&gt;pep docs&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://mypy.readthedocs.io/en/latest/more_types.html#typeddict&#34;&gt;mypy docs&lt;/a&gt;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Home-Server-Refactor</title>
    <id>https://pype.dev/home-server-refactor/</id>
    <updated>2022-04-10T00:00:00Z</updated>
    <published>2022-04-10T00:00:00Z</published>
    <link href="https://pype.dev/home-server-refactor/" rel="alternate" type="text/html"></link>
    <summary type="text">My current homelab setup is not great but it works...</summary>
    <content type="html">&lt;p&gt;My current homelab setup is not great but it works&amp;hellip;&lt;/p&gt;&#xA;&lt;h1 id=&#34;proxmox-on-poweredge-r610&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Proxmox on PowerEdge R610&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;I boot off an SD card and have 1 SSD and 5 HDDs configured as a JBOD array using a Dell H700 SAS controller.&#xA;I cannot boot from a disk using this controller and I can&amp;rsquo;t get the firmware configured in a way to allow it.&#xA;So I have 1 SSD as a ZFS array that I&amp;rsquo;ve been putting my VM images on, and the 5 HDDs are passed through to a TrueNAS VM where I handle all the ZFS stuff there&amp;hellip; kind of meta because I then attached those drives to Proxmox as a CIFS share.&lt;/p&gt;&#xA;&lt;h1 id=&#34;truenas-on-dedicated-box&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;TrueNAS on dedicated box&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;I have an on-prem backup that is just an old desktop running TrueNAS&#xA;I regularly backup the 5 disk RAIDZ2 array from my Proxmox host (managed by a TrueNAS VM) to this backup box&lt;/p&gt;&#xA;&lt;p&gt;Currently there is nothing else running on this machine since it&amp;rsquo;s my &amp;ldquo;backup&amp;rdquo;&lt;/p&gt;&#xA;&lt;h1 id=&#34;jellyfin&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Jellyfin&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;I was HWA for Jellyfin, but hardware passthrough on the R610 is finicky or broken so Jellyfin is running on an Ubuntu host.&lt;/p&gt;&#xA;&lt;p&gt;I could put UBuntu on the R610 and give up &amp;ldquo;true virtualization&amp;rdquo;. Then I&amp;rsquo;d manage the SMB share myself.&#xA;If I do that then I would get rid of &amp;ldquo;users&amp;rdquo; I think, ie. basically forgo least-priviledges since I&amp;rsquo;m not sure how hard that is to manage.&lt;/p&gt;&#xA;&lt;p&gt;On the other hand, direct access to the smb config might make it easier?&lt;/p&gt;&#xA;&lt;p&gt;I have the media array on Jellyfin box setup as NFS which was really easy with ZFS&amp;hellip; I think SMB would be just as easy.&lt;/p&gt;&#xA;&lt;h1 id=&#34;plan-of-attack&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Plan of attack…&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Move all vm disks to individual datasets on the NAS&lt;/li&gt;&#xA;&lt;li&gt;Backup docker data&amp;hellip; not sure how well this will work, maybe just start over?&lt;/li&gt;&#xA;&lt;li&gt;Clean up Ansible playbooks on the user side of things - stick with neville vs just using my own name?&lt;/li&gt;&#xA;&lt;li&gt;Install Ubuntu 20 or 22 on a 2.5&amp;quot; drive that I&amp;rsquo;ll toss in this SSD enclosure (or a usb thumb stick?)&lt;/li&gt;&#xA;&lt;li&gt;Re-deploy everything with ansible-playbook and configure&amp;hellip;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;configuration&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Configuration…&lt;/span&gt; &lt;a href=&#34;#configuration&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;ol start=&#34;0&#34;&gt;&#xA;&lt;li&gt;THE FREAKING NAS -&amp;gt; just import zfs array and configure SMB?&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;1.~~ Nextcloud users and connections.. might be able to just copy the data folder? not sure about the database&amp;hellip; try spinning it up in the sandbox vm and see if stuff is there ~~&#xA;2.~~ *arr suite, media profiles and connections to transmission&amp;hellip; nothing major~~&#xA;3. transmission - should be deploy and go&#xA;4. ombi and jackett should also just work after some config again&#xA;5. &lt;del&gt;traefik should just work&lt;/del&gt;&#xA;6. &lt;del&gt;try to bring up pi-hole from the vm that&amp;rsquo;s already running&lt;/del&gt;&#xA;7. &lt;del&gt;heimdall will hopefully just be copying the data folder from the existind docker one&amp;rsquo;&lt;/del&gt;&#xA;8.~~ booksonic can be reconfigured easily~~&#xA;9. &lt;del&gt;portainer&amp;hellip; hopefully just copying data folder over?&lt;/del&gt;&#xA;10. &lt;del&gt;littlelink&lt;/del&gt;, small-group-notes, and blog (at home) will need manually re-deployed once Ubuntu is installed bare-metal&lt;/p&gt;&#xA;&lt;h2 id=&#34;big-big-big-todos&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;BIG BIG BIG TODOS&lt;/span&gt; &lt;a href=&#34;#big-big-big-todos&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Sanoid/syncoid! Get snapshots going and backups configured with on prem TrueNAS&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Wireguard setup on DA.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;network share on printer for paperless&#xA;&lt;del&gt;4. update peperless in ansible-nas&lt;/del&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;del&gt;Just deploy paperless manually&amp;hellip; monitor/manage with portainer&lt;/del&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;booksonic not seeing audiobooks/podcasts&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;need a smb user to map nas/documents to the printer for paperless&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;wireguard setup now on kps phone, desktop, server (and backup truenas?), and dad&amp;rsquo;s pi&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;del&gt;verify lan services work&lt;/del&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;del&gt;Tdar so Jellyfin can work better&lt;/del&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Snapshot business might be cause of all the docker containers and docker using&#xA;ZFS backend&amp;hellip; take everything down and try removing&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;file browser - currently I just one-clicked in portainer, I want to make a stack with my own config file which I&amp;rsquo;ll rip from techno tip and then add my traefik lables too&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Forget filebrowser - going to just use Nextcloud for how it&amp;rsquo;s supposed to be used.&#xA;3. Need to organize those files in nextcloud&lt;/p&gt;&#xA;&lt;h2 id=&#34;check-this-ran-as-cp-utility-in-tmux-window-no-progress-bars-or-anything-it-s-in-ansible-nas-session-window-3&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;CHECK THIS -&amp;gt;  ran as ‘cp’ utility in tmux window, no progress bars or anything. it’s in ansible-nas session -&amp;gt; window 3&lt;/span&gt; &lt;a href=&#34;#check-this-ran-as-cp-utility-in-tmux-window-no-progress-bars-or-anything-it-s-in-ansible-nas-session-window-3&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Olivet bible stuff going to /tmp/olivet/ -&amp;gt; will move this to nextcloud, ideally by the app via appimage so that the db updates and I don&amp;rsquo;t have to run that occ script&#xA;I wnat to organize &amp;ldquo;home&amp;rdquo; still in nextcloud&lt;/p&gt;&#xA;&lt;p&gt;setup Sanoid&lt;/p&gt;&#xA;&lt;p&gt;clean up bitwarden&#xA;learn nextcloud sharing -&amp;gt; maybe just give a link to grandma?&#xA;rest of todos -&amp;gt; document db and sanoid + zfs.rent&lt;/p&gt;&#xA;&lt;p&gt;Check on mom&amp;rsquo;s will&#xA;do media thing for church - split vocals on mp3/4&lt;/p&gt;&#xA;&lt;p&gt;permission-data playbook changes everything to ansible-nas:ansible-nas but then samba task will re-permission some stuff to root:users&amp;hellip; this looks fine&#xA;I had to add &lt;code&gt;group&lt;/code&gt; to the samba config in my playbook to get user auth to work with samba&#xA;This isn&amp;rsquo;t fully working&amp;hellip; it works from cli but my python process can&amp;rsquo;t write to a folder in dump after 777&amp;hellip;. need to learn more?&#xA;So I can make a file after adding the ansible-nas group to config, but I still cannot make a directory on the smb mount&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;ADDING &lt;code&gt;inherit permission = yes&lt;/code&gt; under &lt;code&gt;[global]&lt;/code&gt; in the smb.conf worked!&lt;/p&gt;&#xA;&lt;p&gt;still not working from printer&amp;hellip;&#xA;I think what I want is to setup 2 scan options - single docs right to paperless, or combined scans to dump, then manually split and send to paperless&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>And-vs-&amp;</title>
    <id>https://pype.dev/and-vs/</id>
    <updated>2022-04-06T00:00:00Z</updated>
    <published>2022-04-06T00:00:00Z</published>
    <link href="https://pype.dev/and-vs/" rel="alternate" type="text/html"></link>
    <summary type="text">I often struggle to remember the correct way to do type comparisons when working in pandas.</summary>
    <content type="html">&lt;p&gt;I often struggle to remember the correct way to do &lt;code&gt;and&lt;/code&gt; type comparisons when working in pandas.&lt;/p&gt;&#xA;&lt;p&gt;I remember learning long long ago that &lt;code&gt;and&lt;/code&gt; and &lt;code&gt;&amp;amp;&lt;/code&gt; are different, the former being lazy boolean evaluation whereas the latter is a bitwise operation.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;I learned a lot from &lt;a href=&#34;https://stackoverflow.com/questions/22646463/and-boolean-vs-bitwise-why-difference-in-behavior-with-lists-vs-nump&#34;&gt;this SO post&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;lists&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Lists&lt;/span&gt; &lt;a href=&#34;#lists&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Python &lt;code&gt;list&lt;/code&gt; objects can contain unlike elements - ie. &lt;code&gt;[True, &#39;foo&#39;, 1, &#39;1&#39;, [1,2,3]]&lt;/code&gt; is a valid list with booleans, strings, integers, and another list.&#xA;Because of this, we can&amp;rsquo;t use &lt;code&gt;&amp;amp;&lt;/code&gt; to compare two lists since they can&amp;rsquo;t be combined in a consistent and meaningful way.&lt;/p&gt;&#xA;&lt;p&gt;However we can use &lt;code&gt;and&lt;/code&gt; since it doesn&amp;rsquo;t do bitwise operations, it just evaluates the boolean value of the list (basically if it&amp;rsquo;s non-empty then &lt;code&gt;bool(my_list)&lt;/code&gt; evaluates to &lt;code&gt;True&lt;/code&gt;)&lt;/p&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s an example:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NO&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;VCS&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;my_list&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;2&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;foo&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NO&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;VCS&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;bool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;my_list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If we compare &lt;code&gt;my_list&lt;/code&gt; with &lt;code&gt;another_list&lt;/code&gt; using &lt;code&gt;and&lt;/code&gt; then the comparision will go:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;if bool(my_list):&#xA;    if bool(another_list):&#xA;       &amp;lt;operation&amp;gt; &#xA;    else:&#xA;       break&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s see another example:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NO&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;VCS&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;another_list&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NO&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;VCS&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;my_list&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;another_list&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;bool(my_list)&lt;/code&gt; evaluated to &lt;code&gt;True&lt;/code&gt;, and &lt;code&gt;bool(another_list)&lt;/code&gt; &lt;em&gt;also&lt;/em&gt; evaluated to &lt;code&gt;True&lt;/code&gt; even though it&amp;rsquo;s full of &lt;code&gt;False&lt;/code&gt; values because the object is non-empty.&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NO&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;VCS&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;my_list&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;another_list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;     &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;foo&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;foo&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So using &lt;code&gt;and&lt;/code&gt; in this case results in a &lt;code&gt;True&lt;/code&gt; conditional, so the &lt;code&gt;print&lt;/code&gt; statement is executed.&lt;/p&gt;&#xA;&lt;p&gt;Feels kind of counter-intuitive at first glance, to me anyways&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;However, we can&amp;rsquo;t use &lt;code&gt;&amp;amp;&lt;/code&gt; because there isn&amp;rsquo;t a meaningful to do bitwise operations over these two lists:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NO&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;VCS&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;my_list&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;another_list&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;╭───────────────────────────────&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Traceback&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;most&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;recent&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;call&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;last&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;────────────────────────────────╮&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;19&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a2a16cebb3da&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cell&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;                                              &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;╰──────────────────────────────────────────────────────────────────────────────────────────────────╯&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;ne&#34;&gt;TypeError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;unsupported&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;operand&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;list&amp;#39;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;list&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;numpy&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Numpy&lt;/span&gt; &lt;a href=&#34;#numpy&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;&lt;code&gt;numpy&lt;/code&gt; arrays are special and they have a lot of fancy vectorization utilities built-in which make them great and fast for mathematical operations but now our logical comparisons need to be handled with a different kind of care.&lt;/p&gt;&#xA;&lt;p&gt;First thing though - without some trickery they do not hold mixed data types like a &lt;code&gt;list&lt;/code&gt; does (necessary, I think, for the vectorized optimization that numpy is built on top of)&lt;/p&gt;&#xA;&lt;p&gt;With that out of the way here&amp;rsquo;s the main thing for this post, we can&amp;rsquo;t just evaluate the &lt;code&gt;bool&lt;/code&gt; of an array - numpy says no no no.&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NO&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;VCS&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;arr&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;array&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NO&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;VCS&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;arr&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;array&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;2&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;True&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;False&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dtype&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;lt;U21&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NO&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;VCS&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;bool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;arr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;╭───────────────────────────────&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Traceback&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;most&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;recent&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;call&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;last&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;────────────────────────────────╮&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;25&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;4e8&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c5dd85b93&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cell&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;                                              &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;╰──────────────────────────────────────────────────────────────────────────────────────────────────╯&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;ne&#34;&gt;ValueError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;The&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;truth&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;of&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;an&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;array&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;with&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;more&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;than&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;one&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;element&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ambiguous&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Use&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;any&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;or&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;all&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;&#xA;&lt;p&gt;This means that using &lt;code&gt;and&lt;/code&gt; with &lt;code&gt;numpy&lt;/code&gt; arrays doesn&amp;rsquo;t really make sense because we probably care about the truth value of each element (bitwise), not the truth value of the array.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Notice that when I print &lt;code&gt;arr&lt;/code&gt; all the elements are a string - and the &lt;code&gt;dtype&lt;/code&gt; is &lt;code&gt;&amp;lt;U21&lt;/code&gt; for all elements.&lt;/p&gt;&#xA;&lt;p&gt;This is not how I instantiated the array so be aware of that behavior with numpy.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;code&gt;&amp;lt;U21&lt;/code&gt; is a dtype expressing the values are &amp;lsquo;Little Endian&amp;rsquo;, Unicode, 12 characters. See &lt;a href=&#34;https://numpy.org/doc/stable/reference/arrays.dtypes.html#specifying-and-constructing-data-types&#34;&gt;here&lt;/a&gt; for docs for docs&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;So for logical comparisions we should look at the error message then&amp;hellip;&#xA;Our handy error message says to try &lt;code&gt;any&lt;/code&gt; or &lt;code&gt;all&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;Because the datatypes in this example are basically strings, using &lt;code&gt;arr.any()&lt;/code&gt; will result in an error that I do not fully understand, but &lt;code&gt;any(arr)&lt;/code&gt; and &lt;code&gt;all(arr)&lt;/code&gt; work&amp;hellip;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NO&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;VCS&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;arr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;any&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;     &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;foo&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;╭───────────────────────────────&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Traceback&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;most&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;recent&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;call&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;last&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;────────────────────────────────╮&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;48&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;25&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ecac52db96&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cell&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;                                              &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;home&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;u_paynen3&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;personal&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;venv&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lib&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;python3&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;.8&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;site&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;packages&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;numpy&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;core&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_methods&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;57&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;_any&lt;/span&gt;                                                                                     &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;                                                                                                  &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;    &lt;span class=&#34;mi&#34;&gt;54&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;_any&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;axis&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dtype&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;keepdims&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;where&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;               &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;    &lt;span class=&#34;mi&#34;&gt;55&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;# Parsing keyword arguments is currently fairly slow, so avoid it for now              │&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;    &lt;span class=&#34;mi&#34;&gt;56&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;   &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;where&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;                                                                      &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;❱&lt;/span&gt;  &lt;span class=&#34;mi&#34;&gt;57&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;   &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;   &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;umr_any&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;axis&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dtype&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;keepdims&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;                                      &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;    &lt;span class=&#34;mi&#34;&gt;58&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;   &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;umr_any&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;axis&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dtype&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;keepdims&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;where&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;where&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;                             &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;    &lt;span class=&#34;mi&#34;&gt;59&lt;/span&gt;                                                                                            &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;    &lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;_all&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;axis&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dtype&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;keepdims&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;where&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;               &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;╰──────────────────────────────────────────────────────────────────────────────────────────────────╯&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;UFuncTypeError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ufunc&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;logical_or&amp;#39;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;did&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;contain&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;loop&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;with&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;signature&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;matching&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;types&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;numpy&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dtype&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;str_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;gt;) -&amp;gt; None&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NO&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;VCS&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;all&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;arr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;     &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;foo&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;foo&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NO&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;VCS&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;any&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;arr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;     &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;foo&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;foo&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let&amp;rsquo;s change the example to just use integers and see what happens:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NO&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;VCS&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;arr2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;array&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NO&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;VCS&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;arr2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;array&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NO&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;VCS&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;arr2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;any&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;     &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;foo&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;foo&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NO&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;VCS&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;arr2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;all&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;     &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;foo&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ah, now some sanity&amp;hellip;&#xA;First, the booleans are stored as integers, which based on this discussion makes sense.&#xA;Next we check if &lt;code&gt;any&lt;/code&gt; values (this is a bitwise operation) are &lt;code&gt;True&lt;/code&gt;, which we see they are so the conditional evaluates to &lt;code&gt;True&lt;/code&gt;.&#xA;Howver, if we check that &lt;code&gt;all&lt;/code&gt; values are &lt;code&gt;True&lt;/code&gt; we see they aren&amp;rsquo;t, the last value is &lt;code&gt;False&lt;/code&gt; or &lt;code&gt;0&lt;/code&gt; so the conditional fails.&lt;/p&gt;&#xA;&lt;p&gt;This is a different way to evaluate logical conditions than with lists and it&amp;rsquo;s because of the special nature of numpy arrays that allows them to be compared bitwise but on the flip side, there isn&amp;rsquo;t a meaningful way to evaluate the &lt;code&gt;truth value&lt;/code&gt; of an array.&lt;/p&gt;&#xA;&lt;h2 id=&#34;pandas&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Pandas&lt;/span&gt; &lt;a href=&#34;#pandas&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Now for &lt;code&gt;pandas&lt;/code&gt;, which under the hood is a lot of &lt;code&gt;numpy&lt;/code&gt; but not fully.&#xA;&lt;code&gt;pandas.Series&lt;/code&gt; objects can hold mixed data types like lists, however to logically evaluate truth values we have to treat them like numpy arrays.&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NO&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;VCS&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Series&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;foo&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NO&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;VCS&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;        &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;      &lt;span class=&#34;n&#34;&gt;foo&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;     &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;    &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;dtype&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;object&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NO&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;VCS&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;bool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;╭───────────────────────────────&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Traceback&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;most&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;recent&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;call&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;last&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;────────────────────────────────╮&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;68e48&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;e81da14&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cell&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;                                              &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;home&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;u_paynen3&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;personal&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;venv&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lib&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;python3&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;.8&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;site&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;packages&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pandas&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;core&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;generic&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1527&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;__nonzero__&lt;/span&gt;                                                                            &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;                                                                                                  &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;    &lt;span class=&#34;mi&#34;&gt;1524&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;                                                                                        &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;    &lt;span class=&#34;mi&#34;&gt;1525&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;   &lt;span class=&#34;nd&#34;&gt;@final&lt;/span&gt;                                                                               &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;    &lt;span class=&#34;mi&#34;&gt;1526&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;   &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;__nonzero__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;                                                               &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;❱&lt;/span&gt;  &lt;span class=&#34;mi&#34;&gt;1527&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;   &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;   &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;ValueError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;                                                                &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;    &lt;span class=&#34;mi&#34;&gt;1528&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;   &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;   &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;   &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;The truth value of a &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;vm&#34;&gt;__name__&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; is ambiguous. &amp;#34;&lt;/span&gt;                 &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;    &lt;span class=&#34;mi&#34;&gt;1529&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;   &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;   &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;   &lt;span class=&#34;s2&#34;&gt;&amp;#34;Use a.empty, a.bool(), a.item(), a.any() or a.all().&amp;#34;&lt;/span&gt;                       &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;    &lt;span class=&#34;mi&#34;&gt;1530&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;   &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;   &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;                                                                                &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;╰──────────────────────────────────────────────────────────────────────────────────────────────────╯&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;ne&#34;&gt;ValueError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;The&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;truth&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;of&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Series&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ambiguous&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Use&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;empty&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;item&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;any&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;or&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;all&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Just like with numpy, we can&amp;rsquo;t evaluate the truth value of the series in a meaningful way, but bitwise operations make perfect sense&amp;hellip;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;any&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;     &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;foo&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;foo&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NO&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;VCS&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;all&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;     &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;foo&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;I thought this was about &lt;code&gt;and&lt;/code&gt; and &lt;code&gt;&amp;amp;&lt;/code&gt;&amp;hellip;&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;Right, so recall that &lt;code&gt;and&lt;/code&gt; is a lazy boolean evaluation (ie. it evaluates the &amp;rsquo;truth value&amp;rsquo; an object) whereas &lt;code&gt;&amp;amp;&lt;/code&gt; does bitwise comparison.&lt;/p&gt;&#xA;&lt;p&gt;What we see then with &lt;code&gt;pandas&lt;/code&gt; and &lt;code&gt;numpy&lt;/code&gt; is that if we want to do logical comparisons, we need to do them bitwise, ie. use &lt;code&gt;&amp;amp;&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Keep in mind though that the data types make a big deal - we can&amp;rsquo;t use &lt;code&gt;&amp;amp;&lt;/code&gt; with strings  because the bitwise operation isn&amp;rsquo;t supported, for strings we need to use the boolean evaluation.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-original-point&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Original Point&lt;/span&gt; &lt;a href=&#34;#the-original-point&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;My main use case for this is finding elements in a dataframe/series based on 2 or more columns aligning row values&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;Say I have a dataframe like this:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NO&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;VCS&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s2&lt;/span&gt;   &lt;span class=&#34;n&#34;&gt;s3&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;  &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;  &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;foo&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;  &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;bar&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;  &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;baz&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;  &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;fee&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;  &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;  &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;   &lt;span class=&#34;n&#34;&gt;fi&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Example use case is I want to get the values in &lt;code&gt;s3&lt;/code&gt; where &lt;code&gt;s&lt;/code&gt; is 1 and &lt;code&gt;s2&lt;/code&gt; is &amp;lsquo;a&amp;rsquo;. ie. I&amp;rsquo;m just after &lt;code&gt;bar&lt;/code&gt; for now&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;Up until now I&amp;rsquo;ve always just tried &lt;code&gt;df.s3[(df.s == 1) and (df.s2 == &amp;quot;a&amp;quot;)]&lt;/code&gt; the first time and every single time I&amp;rsquo;ve gotten this error that I just haven&amp;rsquo;t ever fully understood:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;ne&#34;&gt;ValueError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;The&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;truth&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;of&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Series&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ambiguous&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Use&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;empty&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;item&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;any&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;or&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;all&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But after this deep dive I think I&amp;rsquo;ve grasped that &lt;code&gt;and&lt;/code&gt; doesn&amp;rsquo;t actually do what I want here, and in order to do the bitwise comparision I need to use &lt;code&gt;&amp;amp;&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NO&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;VCS&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;via&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.8.11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;a&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;    &lt;span class=&#34;n&#34;&gt;bar&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;Name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dtype&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;object&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;end&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;End&lt;/span&gt; &lt;a href=&#34;#end&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Hopefully this set of ramblings brings some clarity to &lt;code&gt;and&lt;/code&gt; and &lt;code&gt;&amp;amp;&lt;/code&gt; and you can Google one less error in the future in your logical comparison workflows 😄&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>File-Length</title>
    <id>https://pype.dev/file-length/</id>
    <updated>2022-04-04T00:00:00Z</updated>
    <published>2022-04-04T00:00:00Z</published>
    <link href="https://pype.dev/file-length/" rel="alternate" type="text/html"></link>
    <summary type="text">I have a specific need for counting the number of lines in a file quickly. At work we use S3 for data storage during our Kedro pipeline development, and in...</summary>
    <content type="html">&lt;p&gt;I have a specific need for counting the number of lines in a file quickly.&#xA;At work we use S3 for data storage during our Kedro pipeline development, and in the development process we may end up orphaning several datasets.&#xA;In order to keep our workspace clean I have a short utility that compares the datasets in a Kedro DataCatalog with the files in the relevant S3 location.&lt;/p&gt;&#xA;&lt;p&gt;To get that list I run an internal tool like this:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;kedro our-liter &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; grep s3 &amp;gt;&amp;gt; orphaned_datasets.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This simply parses our internal linter for the lines releated to my s3 linter utility and pipes those lines to a file.&lt;/p&gt;&#xA;&lt;p&gt;To get a quick idea of how out of wack a pipeline is I could open the text file in vim, git it with the &lt;code&gt;G&lt;/code&gt; and see what line number I&amp;rsquo;m on but I&amp;rsquo;m way too lazy for that&amp;hellip;&lt;/p&gt;&#xA;&lt;h2 id=&#34;awk&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;AWK&lt;/span&gt; &lt;a href=&#34;#awk&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;&lt;code&gt;awk &#39;END {print NR}&#39; orphaned_datasets.txt&lt;/code&gt; gives me the number of lines and I can alias this to whatever feels appropriate in my &lt;code&gt;zshrc&lt;/code&gt;!&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;built-ins for the win!&lt;/strong&gt;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Ipython-Prompt</title>
    <id>https://pype.dev/ipython-prompt/</id>
    <updated>2022-04-02T00:00:00Z</updated>
    <published>2022-04-02T00:00:00Z</published>
    <link href="https://pype.dev/ipython-prompt/" rel="alternate" type="text/html"></link>
    <summary type="text">I have a post on starship where I have some notes on how I use starship to make my zsh experience great with a sweet terminal prompt.</summary>
    <content type="html">&lt;p&gt;I have a &lt;a href=&#34;/starship&#34;&gt;post on starship&lt;/a&gt; where I have some notes on how I use starship to make my zsh experience great with a sweet terminal prompt.&lt;/p&gt;&#xA;&lt;p&gt;Now&amp;hellip; I spend quite a bit of time in ipython every day and I got kind of sick of the vanilla experience and wanted something that more closely matched my starship prompt.&lt;/p&gt;&#xA;&lt;p&gt;There&amp;rsquo;s more to customizing ipython I know for sure but here&amp;rsquo;s 2 things I have going for me&amp;hellip;&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I use &lt;a href=&#34;https://pypi.org/project/rich/&#34;&gt;&lt;code&gt;rich&lt;/code&gt;&lt;/a&gt; authored by @&lt;a href=&#34;https://twitter.com/willmcgugan&#34;&gt;Will McGugan&lt;/a&gt; which makes much of my ipython experience great.&#xA;I won&amp;rsquo;t write about that here but you can find my &lt;code&gt;rich&lt;/code&gt; config &lt;a href=&#34;https://github.com/nicpayne713/dotfiles/blob/main/ipython/.ipython/profile_default/startup/01-rich_init.py&#34;&gt;here&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I used &lt;code&gt;pygments&lt;/code&gt; to customize the ipython prompt with my &lt;code&gt;ipython_config.py&lt;/code&gt; and a startup script, next to my &lt;code&gt;rich&lt;/code&gt; one, called &lt;code&gt;99-prompt.py&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The scripts inside &lt;code&gt;~/.ipython/&amp;lt;profile&amp;gt;/startup&lt;/code&gt; are executed in lexigraphical order, so it&amp;rsquo;s nice to name things in the 10&amp;rsquo;s to give room for adding scripts in between others down the line.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h2 id=&#34;my-prompt&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;My prompt&lt;/span&gt; &lt;a href=&#34;#my-prompt&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;My zsh prompt looks a little something like this:&lt;/p&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/zsh-starship-prompt.png&#34; alt=&#34;starship&#34; title=&#34;A starship prompt&#34; /&gt;&#xA;&lt;p&gt;And after my ipython customiztion it currently (subject to much change but this is as of my dotfiles commit #d22088f6be81a58b5f7dfb73b7a4088cbdd9fece on &lt;code&gt;main&lt;/code&gt;).&lt;/p&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/ipython-prompt.png&#34; alt=&#34;ipython&#34; title=&#34;A starship inspired ipython prompt&#34; /&gt;&#xA;&lt;p&gt;Now in ipython I have an indicator of my working directory, git branch, python environment, and a note that I&amp;rsquo;m in &lt;code&gt;ipython&lt;/code&gt; and not &lt;code&gt;zsh&lt;/code&gt;.&#xA;I also configured my prompt to warn me if I&amp;rsquo;m &lt;em&gt;not&lt;/em&gt; in a git directory!&lt;/p&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/ipython-prompt-no-git.png&#34; alt=&#34;ipython-ng&#34; title=&#34;A starship inspired ipython prompt without git&#34; /&gt;&#xA;&lt;p&gt;All in all the customization isn&amp;rsquo;t too bad with just 2 specific files.&lt;/p&gt;&#xA;&lt;h2 id=&#34;ipython_config-py&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;ipython_config.py&lt;/span&gt; &lt;a href=&#34;#ipython_config-py&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;There&amp;rsquo;s several use cases for &lt;code&gt;ipython_config.py&lt;/code&gt; files in several areas on a pc - sometimes you want a common config across users, so you&amp;rsquo;d drop one in &lt;code&gt;/etc/ipython&lt;/code&gt; and othertimes you have your own which is probably at &lt;code&gt;~/.ipython&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;My ipython config mostly has colors defined on &lt;code&gt;pygment tokens&lt;/code&gt; plus a few autorun commands and &lt;code&gt;pyflyby&lt;/code&gt; (see my friend Waylon&amp;rsquo;s post on pyflyby &lt;a href=&#34;https://waylonwalker.com/pyflyby/&#34;&gt;here&lt;/a&gt;)&lt;/p&gt;&#xA;&lt;p&gt;I wanted to match my ipython somewhat to my tmux and vim color schemes, which I model after the vim-airline theme &lt;code&gt;night owl&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;After picking some some colors and saving variables it&amp;rsquo;s a matter of setting colors per token and then referencing those tokens in your version of &lt;code&gt;99-prompt.py&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;You can check out my &lt;code&gt;ipython_config.py&lt;/code&gt; &lt;a href=&#34;https://github.com/nicpayne713/dotfiles/blob/home/ipython/.ipython/profile_default/ipython_config.py&#34;&gt;here&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;For example, I can set &lt;code&gt;Token.Name.Function&lt;/code&gt; to black, and in &lt;code&gt;ipython&lt;/code&gt; then a function&amp;rsquo;s definition will appear in black text. I set mine to cyan to match my theme.&lt;/p&gt;&#xA;&lt;p&gt;For the prompt colors just match the keyword in &lt;code&gt;c.TerminalInteractiveShell.highlighting_style_overrides&lt;/code&gt; with what is referenced inside &lt;a href=&#34;https://github.com/nicpayne713/dotfiles/blob/home/ipython/.ipython/profile_default/startup/99-prompt.py&#34;&gt;99-prompt.py&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;For example, &lt;code&gt;Token.Prompt&lt;/code&gt; is set to &lt;code&gt;bold grey&lt;/code&gt; which gives me the bold chevron symbol you see in the above image that looks like my zsh prompt&lt;/p&gt;&#xA;&lt;p&gt;Then in &lt;code&gt;99-prompt.py&lt;/code&gt; I have this set for the prompt:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;Token&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Prompt&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;❯ &amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;99-prompt-py&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;99-prompt.py&lt;/span&gt; &lt;a href=&#34;#99-prompt-py&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;You don&amp;rsquo;t need to name your script &lt;code&gt;99-prompt.py&lt;/code&gt;, but I wanted to know that it was for my prompt and I wanted it executed last so it made sense.&lt;/p&gt;&#xA;&lt;p&gt;Here I have &lt;code&gt;MyPrompt&lt;/code&gt; class with the prompt symbol defined as above and several other things&amp;hellip;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;MyPrompt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Prompts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;in_prompt_tokens&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cli&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Token&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;OutPrompt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;absolute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Token&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Generic&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Subheading&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_branch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Token&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Generic&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Heading&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_branch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Token&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Class&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;via &amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_venv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Token&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Entity&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;ipython&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;Token&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Prompt&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;shell&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;last_execution_succeeded&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Token&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Generic&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;s2&#34;&gt;&amp;#34;❯ &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Notice I have 2 custom functions here, &lt;code&gt;get_branch&lt;/code&gt; and &lt;code&gt;get_venv&lt;/code&gt; which grab some git info and python env info and return strings I can dump into my prompt as shown above.&lt;/p&gt;&#xA;&lt;p&gt;To finish you drop &lt;code&gt;ip = get_ipython()&lt;/code&gt; and &lt;code&gt;ip.prompts = MyPrompt(ip)&lt;/code&gt; at the bottom of your prompt script and you should be in custom prompt city!&lt;/p&gt;&#xA;&lt;h2 id=&#34;end&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;End&lt;/span&gt; &lt;a href=&#34;#end&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;This is more or less notes for myself on how this works - drop by my &lt;a href=&#34;https://github.com/nicpayne713/dotfiles/tree/home/ipython&#34;&gt;ipython config&lt;/a&gt; in my dotfiles repo to see my full configs for ipython!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Vim-Spell-Check</title>
    <id>https://pype.dev/vim-spell-check/</id>
    <updated>2022-04-01T00:00:00Z</updated>
    <published>2022-04-01T00:00:00Z</published>
    <link href="https://pype.dev/vim-spell-check/" rel="alternate" type="text/html"></link>
    <summary type="text">__</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Did you know you can spell check in Vim?!&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;!DOCTYPE html&gt;&#xA;&lt;html&gt;&#xA;   &lt;head&gt;&#xA;      &lt;title&gt;Vim Spell check&lt;/title&gt;&#xA;   &lt;/head&gt;&#xA;   &lt;body&gt;&#xA;      &lt;h3 id=&#34;without&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Without...&lt;/span&gt; &lt;a href=&#34;#without&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;      &lt;p&gt;Here is a missspelled word.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;  &amp;lt;h3&amp;gt;With!&amp;lt;/h3&amp;gt;&#xA;  &amp;lt;p&amp;gt;Here is a &amp;lt;u&amp;gt;missspelled&amp;lt;/u&amp;gt; word.&amp;lt;/p&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;   &lt;/body&gt;&#xA;&lt;/html&gt;&#xA;&lt;h2 id=&#34;what-is-this-magic&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;What is this magic???&lt;/span&gt; &lt;a href=&#34;#what-is-this-magic&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;&lt;code&gt;set: spell spelllang=en_us&lt;/code&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;custom-words&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Custom words?&lt;/span&gt; &lt;a href=&#34;#custom-words&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Sometimes there&amp;rsquo;s things that are words to you but not the default spell checker&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;Common example: package names!&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;plotly&lt;/code&gt;, &lt;code&gt;streamlit&lt;/code&gt;, &lt;code&gt;psutil&lt;/code&gt;, etc etc&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;You can easily add these to your vim config by hitting &lt;code&gt;zw&lt;/code&gt; ontop of the word!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Polybar-01</title>
    <id>https://pype.dev/polybar-01/</id>
    <updated>2022-04-01T00:00:00Z</updated>
    <published>2022-04-01T00:00:00Z</published>
    <link href="https://pype.dev/polybar-01/" rel="alternate" type="text/html"></link>
    <summary type="text">polybar is an awesome and super customizable status bar for your desktop environment.</summary>
    <content type="html">&lt;p&gt;&lt;a href=&#34;https://github.com/polybar/polybar&#34;&gt;polybar&lt;/a&gt; is an awesome and super customizable status bar for your desktop environment.&lt;/p&gt;&#xA;&lt;p&gt;I use it with i3-gaps on Ubuntu for work and it makes my day just that much better to have a clean and elegant bar with the things in it that I care about.&lt;/p&gt;&#xA;&lt;p&gt;The GitHub has all the instructions you&amp;rsquo;d need to install and get started with an example.&lt;/p&gt;&#xA;&lt;p&gt;I want to make some notes about how I use polybar and customize it.&lt;/p&gt;&#xA;&lt;h2 id=&#34;organization&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Organization&lt;/span&gt; &lt;a href=&#34;#organization&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;First of all, I recently moved my polybar config out of one config file into a modular structure that keeps my config files small and easiser to edit.&lt;/p&gt;&#xA;&lt;p&gt;You can find my config &lt;a href=&#34;https://github.com/nicpayne713/dotfiles/tree/main/polybar&#34;&gt;here&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;The apps or services you put into polybar are called &lt;code&gt;modules&lt;/code&gt;.&#xA;I have moved all of my modules into their own config files and I source them with one centralized &lt;code&gt;include-modules.ini&lt;/code&gt; config.&lt;/p&gt;&#xA;&lt;p&gt;This separation also makes it easier for me to keep my home and work polybars as in sync as possible without duplicating a ton of config!&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./polybar&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── colors.ini&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── config.ini&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── fonts.ini&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── home-modules.ini&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── include-modules.ini&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── launch.sh&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── modules&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── aws.ini&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── battery.ini&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── bluetooth.ini&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── cisco.ini&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── cpu.ini&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── date.ini&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── eth.ini&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── eth_work.ini&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── i3.ini&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── memory.ini&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── nm-editor.ini&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── powermenu.ini&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── pulseaudio-control.ini&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── pulseaudio.ini&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── rofi.ini&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── vpn.ini&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   └── wlan.ini&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;└── work-modules.ini&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; directory, &lt;span class=&#34;m&#34;&gt;24&lt;/span&gt; files&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To break this down there are several configs to see:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;code&gt;colors.ini&lt;/code&gt; is what you&amp;rsquo;d expect - a set of defined colors like &lt;code&gt;foreground&lt;/code&gt;, &lt;code&gt;underline&lt;/code&gt;, etc.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;config.ini&lt;/code&gt; is the general polybar config file where bars are defined. Currently in mine there is a &lt;code&gt;work&lt;/code&gt; and &lt;code&gt;home&lt;/code&gt; bar defined with the modules sourced in from the explicit config files.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;fonts.ini &lt;/code&gt; is like &lt;code&gt;colors.ini&lt;/code&gt; -&amp;gt; you put fonts here. I recommend using a font patched with NerdFont so you get fancy icons! (I use JetBrains Mono)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;include-modules.ini&lt;/code&gt; is where I list out all the config files in &lt;code&gt;modules/&lt;/code&gt; so I can basically source just the &lt;code&gt;include-modules.ini&lt;/code&gt; without explicitly sourcing every module&amp;rsquo;s config in every polybar defintion.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;launch.sh&lt;/code&gt; is a simple shell script to launch the polybar! You&amp;rsquo;ll see mine takes multiple monitors into consideration which I manage via environment variables setup in my &lt;code&gt;.zshenv&lt;/code&gt; file that is different for my work and home setups.&lt;/li&gt;&#xA;&lt;li&gt;Finally there are &lt;code&gt;home-modules.ini&lt;/code&gt; and &lt;code&gt;work-modules.ini&lt;/code&gt; which is where, for each of my bars, I define which modules I want!&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;config&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Config&lt;/span&gt; &lt;a href=&#34;#config&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;My &lt;code&gt;config.ini&lt;/code&gt; file has 2 bar definitions in it - here&amp;rsquo;s my home one:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;include-file&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$DOTFILES/polybar/include-modules.ini&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[bar/home]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;monitor&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;${env:MONITOR:}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;width&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;100%&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;height&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;25&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;radius&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;8.0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;fixed-center&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;true&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;bottom&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;false&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;background&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;${colors.background}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;foreground&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;${colors.foreground}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;include-file&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$DOTFILES/polybar/fonts.ini&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;include-file&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$DOTFILES/polybar/home-modules.ini&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It should be easy to follow - I bring in the &lt;code&gt;include-modules&lt;/code&gt;, set a few colors for the bar like &lt;code&gt;background&lt;/code&gt; and &lt;code&gt;foreground&lt;/code&gt; which are sourced by the &lt;code&gt;colors.ini&lt;/code&gt;, and finally bring in my fonts and home modules via their config files!&lt;/p&gt;&#xA;&lt;p&gt;It&amp;rsquo;s super easy to then change one or two things in the appropriate places rather than combing through one massive config. This also makes it easy for me to seperate my work and home setups.&lt;/p&gt;&#xA;&lt;h2 id=&#34;modules&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Modules&lt;/span&gt; &lt;a href=&#34;#modules&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;There are several builtin modules, like &lt;code&gt;wlan&lt;/code&gt; which gives your wifi status right there in polybar.&lt;/p&gt;&#xA;&lt;p&gt;You can also make custom ones.&#xA;A big-time custom one for me is an indicator of whether or not I have an active AWS token for working with the &lt;code&gt;aws&lt;/code&gt; cli.&lt;/p&gt;&#xA;&lt;p&gt;This is defined in&lt;code&gt; modules/aws.ini&lt;/code&gt; and it looks like this:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[module/aws]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;interval&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;5.0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;custom/script&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;exec&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;has_aws_token&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;click-left&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$HOME/.local/bin/auto_get_aws_token&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;click-right&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;rm -rf ~/.aws/credentials&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Every &lt;code&gt;5&lt;/code&gt; seconds my &lt;code&gt;has_aws_token&lt;/code&gt; script is ran.&#xA;That script looks like this:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#!/bin/bash&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;source&lt;/span&gt; auto_proxy&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;aws sts get-caller-identity &lt;span class=&#34;p&#34;&gt;&amp;amp;&lt;/span&gt;&amp;gt; /dev/null &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;%{T5}%{F#00ff00}  %{F-}%{T-}&amp;#34;&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;||(&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;%{T5}%{F#ff0000} %{F-}%{T-}&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;See how the script echos out a colored icon to indicate the status of my token -&amp;gt; that icon is displayed in the polybar so I have real-time (5 second latency) status of whether or not I can do things in my AWS environment.&lt;/p&gt;&#xA;&lt;p&gt;In the module I also configured actions for &lt;code&gt;click-left&lt;/code&gt; and &lt;code&gt;click-right&lt;/code&gt; which are as straight forward as could be.&lt;/p&gt;&#xA;&lt;h2 id=&#34;my-issues-with-i3&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;My issues with i3&lt;/span&gt; &lt;a href=&#34;#my-issues-with-i3&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;There&amp;rsquo;s a few things to be considerate of if you use &lt;code&gt;i3&lt;/code&gt; such as needing a workaround for a centered bar that &lt;strong&gt;is not&lt;/strong&gt; the full width of the monitor.&#xA;Polybar can look really nice by not taking up the full width of the bar which you can configure in &lt;code&gt;config.ini&lt;/code&gt; with these options:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;width&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;90%&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;offset-x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;5%  # set to (100 - width) / 2&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;However due to an issue with polybar and i3 you need to also set &lt;code&gt;override-redirect = true&lt;/code&gt;.&#xA;BUT then you&amp;rsquo;ll notice that the bar overlaps your i3 windows&amp;hellip; ARGH! what do we do?&lt;/p&gt;&#xA;&lt;p&gt;Quick work around is to set &lt;code&gt;gaps top&lt;/code&gt; in your i3 config if you use i3-gaps&amp;hellip; if not? well, idk&amp;hellip; use gaps&amp;hellip; lol&lt;/p&gt;&#xA;&lt;p&gt;However this introduces another issue - which is then full screen windows will  have polybar sitting on top of them&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;This isn&amp;rsquo;t necessarily a deal breaker, but for me it&amp;rsquo;s worth it to just have the bar go 100% width.&lt;/p&gt;&#xA;&lt;h2 id=&#34;fin&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;FIN&lt;/span&gt; &lt;a href=&#34;#fin&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;There&amp;rsquo;s a tiny intro to polybar and how I organize my config files so things are easy to edit and manage!&#xA;Feel free to grab mine and try it out!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Deques</title>
    <id>https://pype.dev/deques/</id>
    <updated>2022-03-31T00:00:00Z</updated>
    <published>2022-03-31T00:00:00Z</published>
    <link href="https://pype.dev/deques/" rel="alternate" type="text/html"></link>
    <summary type="text">I am working on a project to create a small system monitoring dashboard using the python library.</summary>
    <content type="html">&lt;p&gt;I am working on a project to create a small system monitoring dashboard using the python &lt;code&gt;psutil&lt;/code&gt; library.&lt;/p&gt;&#xA;&lt;p&gt;The repo is &lt;a href=&#34;https://github.com/nicpayne713/not-netdata&#34;&gt;here&lt;/a&gt; (if you want actual system monitoring please use &lt;a href=&#34;https://www.netdata.cloud/&#34;&gt;netdata&lt;/a&gt;).&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;m using &lt;code&gt;streamlit&lt;/code&gt; and &lt;code&gt;plotly&lt;/code&gt; for the webserver, design, and plotting at the moment.&lt;/p&gt;&#xA;&lt;h2 id=&#34;my-use-case&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;My Use Case&lt;/span&gt; &lt;a href=&#34;#my-use-case&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I needed a way to refresh my plotly charts with a fixed window of time so that I&amp;rsquo;m able to just see relevant recent data instead of cramming all data for all time into one plot that&amp;rsquo;s 500 pixels wide&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;Checking the length of arrays or lists every time I get a new piece of data feels kind of dumb and I thought &amp;ldquo;python must have a way to do this&amp;rdquo;&amp;hellip;&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;This&amp;rdquo; meaning, update values in a fixed length array without reallocating memory or recreating a copy of the list&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h2 id=&#34;deques&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Deques&lt;/span&gt; &lt;a href=&#34;#deques&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Enter the &lt;code&gt;deque&lt;/code&gt;.&#xA;It means &amp;ldquo;double ended queue&amp;rdquo; and is in general an &lt;code&gt;Iterable&lt;/code&gt; that you can append values to either side or pop values from either side.&lt;/p&gt;&#xA;&lt;p&gt;The init signature is straightforward enough and I&amp;rsquo;m sure there&amp;rsquo;s more to them than I know yet but here&amp;rsquo;s how I use it&amp;hellip;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;collections&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deque&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;my_deque&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deque&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This gives us &lt;code&gt;my_deque&lt;/code&gt;, created from an iterable, with several familiar methods like &lt;code&gt;index&lt;/code&gt;, &lt;code&gt;extend&lt;/code&gt;, &lt;code&gt;append&lt;/code&gt;, etc.&#xA;However there&amp;rsquo;s some new ones too such as &lt;code&gt;appendleft&lt;/code&gt; and &lt;code&gt;popleft&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;my_deque&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;appendleft&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;my_dequqe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deque&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;my_deque&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;popleft&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;--&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;markata&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;attribution&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;--&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;my_deque&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deque&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;These are handy ways to manipulate the iterable that I needed for the arrays I plot with plotly!&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;See my follow-up to this on using Deques with plotly and streamlit to create a quick &amp;ldquo;dashboard&amp;rdquo; with live streaming data!&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;/plotly-and-streamlit&#34;&gt;follow-up&lt;/a&gt;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Plotly-And-Streamlit</title>
    <id>https://pype.dev/plotly-and-streamlit/</id>
    <updated>2022-03-31T00:00:00Z</updated>
    <published>2022-03-31T00:00:00Z</published>
    <link href="https://pype.dev/plotly-and-streamlit/" rel="alternate" type="text/html"></link>
    <summary type="text">I use for any EDA I ever have to do at work. It&#39;s super easy to spin up a small dashboard to filter and view dataframes in, live, without the fallbacks of...</summary>
    <content type="html">&lt;h2 id=&#34;streamlit&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Streamlit&lt;/span&gt; &lt;a href=&#34;#streamlit&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I use &lt;code&gt;streamlit&lt;/code&gt; for any EDA I ever have to do at work.&#xA;It&amp;rsquo;s super easy to spin up a small dashboard to filter and view dataframes in, live, without the fallbacks of Jupyter notebooks (kernels dying, memory bloat, a billion &amp;ldquo;Untitled N.ipynb&amp;rdquo; files, etc.)&lt;/p&gt;&#xA;&lt;p&gt;At the highest level, streamlit lets you write a python script and call &lt;code&gt;streamlit run my_script.py&lt;/code&gt; which will open up a web server with your streamlit stuff.&#xA;The dashboard refreshes whenever you change the script so you can add capabilities in real time, super fast!&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;ll show an example of using &lt;code&gt;streamlit&lt;/code&gt; and &lt;code&gt;plotly&lt;/code&gt; to make a live dashboard to monitor system memory usage with &lt;code&gt;psutil&lt;/code&gt;.&#xA;This is apart of my posts on &lt;a href=&#34;/psutil&#34;&gt;psutil&lt;/a&gt; and &lt;a href=&#34;/deques&#34;&gt;deques&lt;/a&gt;&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;example at the bottom!&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;plotly&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Plotly&lt;/span&gt; &lt;a href=&#34;#plotly&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I&amp;rsquo;m not going to make a big time intro to plotly here - there&amp;rsquo;s a billion resources on the interwebs and the docs are really good.&lt;/p&gt;&#xA;&lt;p&gt;Suffice it to say it&amp;rsquo;s my goto plotting library for basically any and all needs.&#xA;I&amp;rsquo;m currently exploring it for live data streaming as I&amp;rsquo;m not sure it&amp;rsquo;s the best solution but it&amp;rsquo;s the one I&amp;rsquo;m familiar with.&lt;/p&gt;&#xA;&lt;p&gt;For my &lt;a href=&#34;https://github.com/nicpayne713/not-netdata&#34;&gt; not-netdata &lt;/a&gt; project of visualizing live system resource data I  first need a way of appending data and popping data in and out of an array at every data refresh cycle to keep my plots looking nice with a fixed time window.&lt;/p&gt;&#xA;&lt;p&gt;See &lt;a href=&#34;/deques&#34;&gt;deques&lt;/a&gt; for a short intro to the datatype I&amp;rsquo;m using.&lt;/p&gt;&#xA;&lt;p&gt;First step is to initialize some objects to store data in.&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;MutableSequence&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Optional&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;defaultdict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;deque&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;arr_size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deque&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;arr_size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;used_memory&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deque&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;arr_size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;data&lt;/code&gt; is a dictionary that I&amp;rsquo;ll store deques in. The dictionary keys will be the type of data, in this case &lt;code&gt;time&lt;/code&gt; and &lt;code&gt;used_memory&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;I fix an array size, &lt;code&gt;arr_size&lt;/code&gt; to just 10 for now&lt;/p&gt;&#xA;&lt;p&gt;Then I initialize the values for &lt;code&gt;time&lt;/code&gt; and &lt;code&gt;used_memory&lt;/code&gt; as &lt;code&gt;deque&lt;/code&gt;s of length &lt;code&gt;arr_size&lt;/code&gt;.&#xA;Simple enough!&lt;/p&gt;&#xA;&lt;p&gt;Next is to fill those deques with some relevant data.&#xA;I&amp;rsquo;m not actually sure if this is the best way to do this but here&amp;rsquo;s what I have done so far:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;refresh_data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;global&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;memory&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;psutil&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;virtual_memory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;strftime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;%Y-%m-&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;%d&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; %H:%M:%S&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;localtime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()))&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;used_memory&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;memory&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;used&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;//&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1024&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;popleft&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;used_memory&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;popleft&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you ignore my usage of &lt;code&gt;global&lt;/code&gt; you&amp;rsquo;ll see that I can just &lt;code&gt;append&lt;/code&gt; to each deque like it was a list.&lt;/p&gt;&#xA;&lt;p&gt;But then to keep the relevant data in the deque, and to keep the length fixed, I simply &lt;code&gt;popleft&lt;/code&gt; to remove the oldest datapoint!&lt;/p&gt;&#xA;&lt;h2 id=&#34;a-trivial-dashboard&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;A trivial dashboard&lt;/span&gt; &lt;a href=&#34;#a-trivial-dashboard&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Now I&amp;rsquo;ll prove just how easy it is to get a live data dashboard up and running with just a few lines of code thanks to streamlit!&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;vm&#34;&gt;__name__&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;st&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;header&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;memory chart&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;stats&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;st&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;empty&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;refresh_data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;stats&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;plotly_chart&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;px&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;used_memory&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;n&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Memory usage stored in a deque!&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;               &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sleep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;st&lt;/code&gt; is the streamlit alias (imports shows at the bottom full example).&#xA;&lt;code&gt;st.header&lt;/code&gt; puts a nice header on the page.&#xA;&lt;code&gt;st.empty&lt;/code&gt; initializes an empty &lt;code&gt;streamlit container&lt;/code&gt; in which we&amp;rsquo;ll put a &lt;code&gt;plotly.express&lt;/code&gt; figure.&lt;/p&gt;&#xA;&lt;p&gt;At each iteration we&amp;rsquo;ll &lt;code&gt;refresh_data()&lt;/code&gt; which &lt;code&gt;appends&lt;/code&gt; and &lt;code&gt;pops&lt;/code&gt; data in the deques in the &lt;code&gt;data&lt;/code&gt; dictionary.&#xA;Then we update the &lt;code&gt;stats&lt;/code&gt; container with a plotly graph and the refresh happens seamlessly.&lt;/p&gt;&#xA;&lt;p&gt;All in all the script looks like this:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;collections&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;defaultdict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deque&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;time&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;typing&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;MutableSequence&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Optional&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;plotly&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;express&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;px&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;psutil&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;streamlit&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;st&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;MutableSequence&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Optional&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;defaultdict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;deque&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;arr_size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deque&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;arr_size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;used_memory&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deque&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;arr_size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;refresh_data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;global&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;memory&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;psutil&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;virtual_memory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;strftime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;%Y-%m-&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;%d&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; %H:%M:%S&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;localtime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()))&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;used_memory&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;memory&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;used&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;//&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1024&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;popleft&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;used_memory&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;popleft&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;memory_chart&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;fig&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;px&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;used_memory&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Memory usage stored in a deque!&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fig&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;vm&#34;&gt;__name__&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;st&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;header&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;memory chart&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;stats&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;st&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;empty&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;refresh_data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;stats&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;plotly_chart&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;memory_chart&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sleep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can save this as &lt;code&gt;my_dash.py&lt;/code&gt; and run with &lt;code&gt;streamlit run my_dash.py&lt;/code&gt; and should see something like the following!&lt;/p&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/plotly-streamlit.gif&#34; alt=&#34;plotly&#34; title=&#34;Plotly in Streamlit&#34; /&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Starship</title>
    <id>https://pype.dev/starship/</id>
    <updated>2022-03-25T00:00:00Z</updated>
    <published>2022-03-25T00:00:00Z</published>
    <link href="https://pype.dev/starship/" rel="alternate" type="text/html"></link>
    <summary type="text">If you spend time in the terminal then you&#39;ll want it to look somewhat pleasing to the eye. I used to ssh into servers with no customization, use to edit a...</summary>
    <content type="html">&lt;p&gt;If you spend time in the terminal then you&amp;rsquo;ll want it to look somewhat pleasing to the eye.&#xA;I used to ssh into servers with no customization, use &lt;code&gt;vi&lt;/code&gt;  to edit a file or two, then get back to my regularly scheduled programming in VS C**e&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;One of the first steps for me loving my terminal was a beautiful prompt&amp;hellip;&lt;/p&gt;&#xA;&lt;h2 id=&#34;prompt&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Prompt&lt;/span&gt; &lt;a href=&#34;#prompt&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;The default sh/bash/zsh prompts are&amp;hellip; to put it lightly&amp;hellip; garbage&amp;hellip; I can&amp;rsquo;t speak for other shells like fish simply because I do not use them but let me justify my trash talk.&lt;/p&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s the default &lt;code&gt;sh&lt;/code&gt; prompt&amp;hellip;&lt;/p&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/sh-prompt.png&#34; alt=&#34;sh&#34; title=&#34;A default sh prompt&#34; /&gt;&#xA;&lt;p&gt;Then switching to &lt;code&gt;zsh&lt;/code&gt; you get something marginally better (plus tab completion!)&lt;/p&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/zsh-prompt.png&#34; alt=&#34;zsh&#34; title=&#34;A default zsh prompt&#34; /&gt;&#xA;&lt;p&gt;But this still is super gross&amp;hellip; there&amp;rsquo;s nothing to indicate file types and no status information readily available (ie. &lt;code&gt;git status&lt;/code&gt; etc.)&lt;/p&gt;&#xA;&lt;h2 id=&#34;oh-my-zsh&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Oh-My-Zsh!&lt;/span&gt; &lt;a href=&#34;#oh-my-zsh&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Now there are several ways to make your prmompt nicer depending on your shell (terminal emulator plays a role too).&#xA;Now I use &lt;code&gt;zsh&lt;/code&gt; and there&amp;rsquo;s a great tool out there &lt;a href=&#34;https://ohmyz.sh/&#34;&gt;oh-my-zsh&lt;/a&gt; that brings a crazy amount of customization to the terminal experience.&lt;/p&gt;&#xA;&lt;p&gt;I do not use &lt;code&gt;oh-my-zsh&lt;/code&gt; for theming though and that&amp;rsquo;s simply because of my other choices - I use &lt;code&gt;kitty&lt;/code&gt; themes since I understood the implementation better.&#xA;Kitty themes though - do not give me a nice prompt.&lt;/p&gt;&#xA;&lt;p&gt;The default prompt you get with &lt;code&gt;oh-my-zsh&lt;/code&gt; themes isn&amp;rsquo;t bad though (and you can pick from several default themes)&amp;hellip;&lt;/p&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/zsh-oh-my-zsh-prompt.png&#34; alt=&#34;omz&#34; title=&#34;A default oh-my-zsh prompt&#34; /&gt;&#xA;&lt;p&gt;Notice that you get some nice coloring and some default &lt;code&gt;git&lt;/code&gt; status stuff, mainly the branch you are on.&#xA;There&amp;rsquo;s plugins to show you more and that&amp;rsquo;s all well and good, but again it&amp;rsquo;s not my choice&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;If I don&amp;rsquo;t use this then what&amp;rsquo;s my goto?&lt;/p&gt;&#xA;&lt;h2 id=&#34;starship&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Starship&lt;/span&gt; &lt;a href=&#34;#starship&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://starship.rs/&#34;&gt;starship&lt;/a&gt; is a cross-shell prompt with nice default and super easy customizaton!&lt;/p&gt;&#xA;&lt;p&gt;To get started click that link and follow the &amp;ldquo;Getting Started&amp;rdquo; button - it&amp;rsquo;s incredibly fast to get up and running with sane defaults.&lt;/p&gt;&#xA;&lt;p&gt;The default starship config is plenty nice but I got a little tired of emojis in my prompt and wanted to switch to icons instead&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;To get started with your own customizaton you add a &lt;code&gt;starship.toml&lt;/code&gt; file to &lt;code&gt;~/.config&lt;/code&gt;&#xA;My starship config is found &lt;a href=&#34;https://github.com/nicpayne713/dotfiles/blob/main/starship/.config/starship.toml&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Note you need a font installed patched with nerdfonts - I use JetBrains Mono&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Now I have a beautiful prompt with relevant information that&amp;rsquo;s a dream to look at!&lt;/p&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/zsh-starship-prompt.png&#34; alt=&#34;starship&#34; title=&#34;A starship prompt&#34; /&gt;&#xA;&lt;p&gt;I have configured my starship to show me relevant &lt;code&gt;git status&lt;/code&gt; options (stashes, untracked files, etc etc.)&#xA;I also have starship show me if I&amp;rsquo;m in a git repo, what branch I&amp;rsquo;m on, if I&amp;rsquo;m in a python project and if so what virtual environment is active.&#xA;I do some work in AWS at work and so I have starship show me if my &lt;code&gt;aws cli&lt;/code&gt; is configured to the right region for whichever project I&amp;rsquo;m in!&lt;/p&gt;&#xA;&lt;p&gt;There&amp;rsquo;s a billion more options and after a few minutes of play it becomes really easy and intuitive to customize colors, icons, etc.&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>self-hosted-media</title>
    <id>https://pype.dev/self-hosted-media/</id>
    <updated>2022-03-24T00:00:00Z</updated>
    <published>2022-03-24T00:00:00Z</published>
    <link href="https://pype.dev/self-hosted-media/" rel="alternate" type="text/html"></link>
    <summary type="text">Self-hosting 1 or several media servers is another common homelab use-case. Getting content for your media servers is up to you, but I&#39;ll show a few ways...</summary>
    <content type="html">&lt;p&gt;Self-hosting 1 or several media servers is another common homelab use-case.&#xA;Getting content for your media servers is up to you, but I&amp;rsquo;ll show a few ways here to get content somewhat easily!&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;YouTube Disclaimer at Bottom&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;you-get&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;you-get&lt;/span&gt; &lt;a href=&#34;#you-get&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;&lt;code&gt;you-get&lt;/code&gt; is a nice cli for grabbing media content off the web.&lt;/p&gt;&#xA;&lt;h3 id=&#34;installation&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Installation&lt;/span&gt; &lt;a href=&#34;#installation&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;&lt;code&gt;pip install you-get&lt;/code&gt; or use ad-hoc with &lt;code&gt;pipx run you-get &amp;lt;url&amp;gt;&lt;/code&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;usage&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Usage&lt;/span&gt; &lt;a href=&#34;#usage&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;For example if I wanted to catch up on ancient Chinese military tactics I may go for &lt;code&gt;The Art of War&lt;/code&gt; off the Internet Archive&amp;hellip;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sandbox  🌱 main 🗑️  ×3🛤️  ×6via 🐍 v3.8.11 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;sandbox&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;  took 15s&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ you-get https://archive.org/details/art_of_war_librivox -i&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Site:       Archive.org&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Title:      The Art of War : Sun Tzu : Free Download, Borrow, and Streaming : Internet Archive&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Type:       MP3 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;audio/mpeg&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Size:       3.87 MiB &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;4055167&lt;/span&gt; Bytes&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;the &lt;code&gt;-i&lt;/code&gt; is showing me the info of what would be downloaded without the flag (it&amp;rsquo;s like a dry run)&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sandbox  🌱 main 🗑️  ×3🛤️  ×6via 🐍 v3.8.11 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;sandbox&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ you-get https://archive.org/details/art_of_war_librivox&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Site:       Archive.org&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Title:      The Art of War : Sun Tzu : Free Download, Borrow, and Streaming : Internet Archive&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Type:       MP3 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;audio/mpeg&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Size:       3.87 MiB &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;4055167&lt;/span&gt; Bytes&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Downloading The Art of War : Sun Tzu : Free Download, Borrow, and Streaming : Internet Archi.mp3 ...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; 100% &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;  3.9/  3.9MB&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; ├████████████████████████████████████████████████████████████┤&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;1/1&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;  &lt;span class=&#34;m&#34;&gt;917&lt;/span&gt; kB/s&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now I can toss that mp3 onto my &lt;code&gt;booksonic&lt;/code&gt; server and study for world domination while I do the dishes!&lt;/p&gt;&#xA;&lt;h2 id=&#34;pytube&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;pytube&lt;/span&gt; &lt;a href=&#34;#pytube&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;&lt;code&gt;pytube&lt;/code&gt; is a python implementation of a &lt;a href=&#34;##YouTube&#34;&gt;youtube downloader &lt;/a&gt; that works at the command line or in python!&lt;/p&gt;&#xA;&lt;h3 id=&#34;installation-1&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Installation&lt;/span&gt; &lt;a href=&#34;#installation-1&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://pytube.io/en/latest/&#34;&gt;docs&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;pip install pytube&lt;/code&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;usage-1&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Usage&lt;/span&gt; &lt;a href=&#34;#usage-1&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;&lt;code&gt;pytube&lt;/code&gt; has a lot of functionality, but a quick one would be the &lt;code&gt;--list&lt;/code&gt; so you can see what qualities are available&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sandbox   main ️  ×3️  ×7via  v3.8.11 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;sandbox&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;  took 2m49s&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ pytube https://www.youtube.com/watch&lt;span class=&#34;se&#34;&gt;\?&lt;/span&gt;v&lt;span class=&#34;se&#34;&gt;\=&lt;/span&gt;LDU_Txk06tM  --list&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Loading video...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;17&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/3gpp&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;144p&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;8fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;mp4v.20.3&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;acodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;mp4a.40.2&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;True&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;18&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;360p&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;avc1.42001E&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;acodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;mp4a.40.2&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;True&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;22&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;720p&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;avc1.64001F&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;acodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;mp4a.40.2&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;True&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;313&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/webm&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;2160p&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;vp9&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;401&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;2160p&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;av01.0.12M.08&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;271&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/webm&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;1440p&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;vp9&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;400&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;1440p&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;av01.0.12M.08&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;137&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;1080p&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;avc1.640028&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;248&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/webm&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;1080p&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;vp9&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;399&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;1080p&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;av01.0.08M.08&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;136&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;720p&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;avc1.4d401f&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;247&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/webm&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;720p&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;vp9&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;398&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;720p&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;av01.0.05M.08&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;135&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;480p&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;avc1.4d401f&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;244&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/webm&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;480p&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;vp9&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;397&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;480p&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;av01.0.04M.08&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;134&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;360p&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;avc1.4d401e&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;243&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/webm&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;360p&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;vp9&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;396&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;360p&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;av01.0.01M.08&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;133&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;240p&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;avc1.4d4015&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;242&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/webm&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;240p&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;vp9&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;395&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;240p&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;av01.0.00M.08&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;160&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;144p&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;avc1.4d400c&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;278&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/webm&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;144p&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;vp9&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;394&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;144p&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;av01.0.00M.08&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;139&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;audio/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;abr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;48kbps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;acodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;mp4a.40.5&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;audio&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;140&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;audio/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;abr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;128kbps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;acodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;mp4a.40.2&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;audio&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;249&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;audio/webm&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;abr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;50kbps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;acodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;opus&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;audio&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;250&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;audio/webm&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;abr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;70kbps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;acodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;opus&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;audio&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;Stream: &lt;span class=&#34;nv&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;251&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;audio/webm&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;abr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;160kbps&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;acodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;opus&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;audio&amp;#34;&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;pytube &amp;lt;url&amp;gt; --itag &amp;lt;&amp;gt;&lt;/code&gt; will download the specific &lt;code&gt;itag&lt;/code&gt; from the list.&lt;/p&gt;&#xA;&lt;p&gt;Notice that some &lt;code&gt;itags&lt;/code&gt; are videos and others audio - so you can download just the music of a YT video.&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;pytube&lt;/code&gt; also works in python&amp;hellip;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;↪&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;v3&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;.8.11&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;pytube&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;YouTube&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sandbox&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;↪&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;v3&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;.8.11&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;YouTube&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;https://www.youtube.com/watch?v=LDU_Txk06tM&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;streams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;17&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/3gpp&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;144p&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;8fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;mp4v.20.3&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;acodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;mp4a.40.2&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;True&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;18&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;360p&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;avc1.42001E&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;acodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;mp4a.40.2&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;True&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;22&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;720p&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;avc1.64001F&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;acodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;mp4a.40.2&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;True&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;313&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/webm&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;2160p&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;vp9&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;401&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;2160p&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;av01.0.12M.08&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;271&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/webm&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;1440p&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;vp9&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;400&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;1440p&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;av01.0.12M.08&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;137&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;1080p&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;avc1.640028&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;248&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/webm&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;1080p&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;vp9&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;399&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;1080p&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;av01.0.08M.08&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;136&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;720p&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;avc1.4d401f&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;247&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/webm&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;720p&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;vp9&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;398&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;720p&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;av01.0.05M.08&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;135&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;480p&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;avc1.4d401f&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;244&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/webm&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;480p&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;vp9&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;397&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;480p&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;av01.0.04M.08&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;134&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;360p&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;avc1.4d401e&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;243&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/webm&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;360p&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;vp9&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;396&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;360p&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;av01.0.01M.08&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;133&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;240p&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;avc1.4d4015&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;242&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/webm&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;240p&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;vp9&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;395&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;240p&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;av01.0.00M.08&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;160&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;144p&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;avc1.4d400c&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;278&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/webm&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;144p&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;vp9&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;394&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;144p&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fps&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;30fps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vcodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;av01.0.00M.08&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;video&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;139&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;audio/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;abr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;48kbps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;acodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;mp4a.40.5&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;audio&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;140&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;audio/mp4&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;abr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;128kbps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;acodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;mp4a.40.2&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;audio&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;249&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;audio/webm&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;abr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;50kbps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;acodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;opus&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;audio&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;250&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;audio/webm&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;abr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;70kbps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;acodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;opus&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;audio&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itag&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;251&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mime_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;audio/webm&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;abr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;160kbps&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;acodec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;opus&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;progressive&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;False&amp;#34;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;audio&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;youtube-frontends&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;YouTube Frontends&lt;/span&gt; &lt;a href=&#34;#youtube-frontends&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;There&amp;rsquo;s 2 really good options for self-hosting a YT front-end&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/bbilly1/tubearchivist&#34;&gt;Tube Archivist&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/Tzahi12345/YoutubeDL-Material&#34;&gt;YouTubeDL-Material&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;They have their pros and cons.&#xA;You can also build yourself with the above utilities and use Plex or Jellyfin to serve up videos&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Your self-hosting journey is up to you!&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;youtube&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;YouTube&lt;/span&gt; &lt;a href=&#34;#youtube&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Downloading YouTube videos is a bit of a sore topic&amp;hellip; Mainly you don&amp;rsquo;t to hurt creators who rely on YT ad revenue for their livlihood.&lt;/p&gt;&#xA;&lt;p&gt;Then again, maybe you&amp;rsquo;re a vigilante who knows that YT also monetizes videos for their &lt;em&gt;own&lt;/em&gt; gain and that the creators don&amp;rsquo;t see that money either!&lt;/p&gt;&#xA;&lt;p&gt;The solution is pretty easy and is 2-fold&amp;hellip;&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Download YT videos&lt;/li&gt;&#xA;&lt;li&gt;Personally support the content creators you follow via paypall, patreon, or whatever else they might have set-up&amp;hellip;. even a buck or two a month is more than they&amp;rsquo;d get from your ad revenue explicitly plus it all goes to them!&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Skimpy</title>
    <id>https://pype.dev/skimpy/</id>
    <updated>2022-03-23T00:00:00Z</updated>
    <published>2022-03-23T00:00:00Z</published>
    <link href="https://pype.dev/skimpy/" rel="alternate" type="text/html"></link>
    <summary type="text">I work with data a lot, but the nature of my job isn&#39;t to dive super deep into a small amount of datasets, I&#39;m often jumping between several projects every...</summary>
    <content type="html">&lt;h2 id=&#34;eda&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;EDA&lt;/span&gt; &lt;a href=&#34;#eda&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I work with data a lot, but the nature of my job isn&amp;rsquo;t to dive super deep into a small amount of datasets,&#xA;I&amp;rsquo;m often jumping between several projects every day and need to just get a super quick glance at some tables to get a high level view.&lt;/p&gt;&#xA;&lt;p&gt;When I&amp;rsquo;m doing more interactive exploration I&amp;rsquo;ve graduated from Jupyter cells with &lt;code&gt;df_N.head()&lt;/code&gt; to using an amazing tool called &lt;a href=&#34;https://www.visidata.org/&#34;&gt;visidata&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;However, Visidata is a terminal based application and I&amp;rsquo;m often in an iPython console&amp;hellip; so is there a way to move even faster for my super quick summary views?&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;yes!&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;skimpy&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Skimpy&lt;/span&gt; &lt;a href=&#34;#skimpy&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;First thing to do is &lt;code&gt;pip install skimpy&lt;/code&gt; and then it&amp;rsquo;s as easy to get some summary stats with &lt;code&gt;skimpy &amp;lt;data&amp;gt;&lt;/code&gt;&lt;/p&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/skimpy-zsh.png&#34; alt=&#34;Skimpy ZSH&#34; title=&#34;A fancy data summary in the shell&#34; /&gt;&#xA;&lt;p&gt;This is super nice for seeing missing values in particular as well as the distribution shape of the data.&lt;/p&gt;&#xA;&lt;h2 id=&#34;ipython&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;iPython&lt;/span&gt; &lt;a href=&#34;#ipython&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;But wait&amp;hellip; I just said I&amp;rsquo;m normally in an iPython session but that was called from zsh.. If I&amp;rsquo;m hoping back into zsh I might as well use visidata to have more powerful exploration at my fingertips.&#xA;So&amp;hellip; can I see this table quickly without breaking my iPython workflow?&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Of course you can with magic!&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/skimpy-ipython.png&#34; alt=&#34;Skimpy iPython&#34; title=&#34;A fancy data summary in iPython&#34; /&gt;&#xA;&lt;p&gt;The above assumes you&amp;rsquo;re looking at a file, like you would in the terminal.&#xA;&lt;code&gt;skimpy&lt;/code&gt; works even better in iPython with &lt;code&gt;from skimpy import skim&lt;/code&gt; then pass any DataFrame to &lt;code&gt;skim&lt;/code&gt;!&lt;/p&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/skimpy-ipython2.png&#34; alt=&#34;Skimpy iPython2&#34; title=&#34;A fancy data summary in iPython&#34; /&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Truenas-And-Wireguard</title>
    <id>https://pype.dev/truenas-and-wireguard/</id>
    <updated>2022-03-23T00:00:00Z</updated>
    <published>2022-03-23T00:00:00Z</published>
    <link href="https://pype.dev/truenas-and-wireguard/" rel="alternate" type="text/html"></link>
    <summary type="text">One of the most common use cases for self-hosting anything is a file share system. I have been a fan of TrueNAS for a while. I currently use TrueNAS Core at...</summary>
    <content type="html">&lt;h2 id=&#34;nas&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;NAS&lt;/span&gt; &lt;a href=&#34;#nas&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;One of the most common use cases for self-hosting anything is a file share system.&#xA;I have been a fan of &lt;a href=&#34;https://www.truenas.com/&#34;&gt;TrueNAS&lt;/a&gt; for a while.&#xA;I currently use TrueNAS Core at home, and plan to consider transitioning to TrueNAS Scale soon.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Blog post forthcoming on that!&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;vpn&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;VPN&lt;/span&gt; &lt;a href=&#34;#vpn&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I don&amp;rsquo;t write a ton about homelabbing yet but one of the first things to set up whether you have a massive homelab or a little raspberry pi would be a self-hosted VPN.&#xA;I have notes on wireguard &lt;a href=&#34;%22/wireguard%22&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;I finally have a need to put my TrueNAS box on my wireguard network in order to transfer files to other devices that are outside my LAN.&lt;/p&gt;&#xA;&lt;p&gt;There is a handy tutorial on setting this up via the GUI &lt;a href=&#34;https://www.truenas.com/docs/core/network/wireguard/&#34;&gt;here&lt;/a&gt;.&#xA;They walk you through setting up 2 tunables wireguard. One to enable the the connection and one to setup the network interface.&#xA;Next you create a &lt;code&gt;Post Init&lt;/code&gt; script which will check that the right directories exist and will copy the wireguard config that hasn&amp;rsquo;t been made yet to the proper location and finally starts wireguard.&lt;/p&gt;&#xA;&lt;p&gt;The above is just copy/paste from the tutorial but the final step, although not super tricky, isn&amp;rsquo;t the same for everyone as it depends on your wireguard config and network setup.&lt;/p&gt;&#xA;&lt;p&gt;The final step is for you create the relevant wireguard config (see my post but I just use &lt;code&gt;pivpn -a&lt;/code&gt;) and send that config over to your TrueNAS box!&lt;/p&gt;&#xA;&lt;p&gt;For me this final work flow looked like this:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ssh user@vpn-server&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pivpn -a&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;follow prompts&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;scp ~/configs/truenas.conf root@&amp;lt;truenas ip&amp;gt;:/root/wg0.conf&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;bug&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Bug?&lt;/span&gt; &lt;a href=&#34;#bug&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;The script in the tutorial for starting the wireguard service is straight forward enough however my TrueNAS box didn&amp;rsquo;t get the wireguard interface up and running on reboot.&lt;/p&gt;&#xA;&lt;p&gt;Easy enough solution:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ssh root@&amp;lt;truenas ip&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/usr/local/etc/rc.d/wireguard start&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can check that the interface is now working with &lt;code&gt;ifconfig&lt;/code&gt; and should see something like the following:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;wg0: &lt;span class=&#34;nv&#34;&gt;flags&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;8051&amp;lt;UP,POINTOPOINT,RUNNING,MULTICAST&amp;gt; metric &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; mtu &lt;span class=&#34;m&#34;&gt;1420&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nv&#34;&gt;options&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;80000&amp;lt;LINKSTATE&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        inet x.x.x.x --&amp;gt; x.x.x.x netmask 0xffffff00&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        groups: tun&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        nd6 &lt;span class=&#34;nv&#34;&gt;options&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;101&amp;lt;PERFORMNUD,NO_DAD&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        Opened by PID &lt;span class=&#34;m&#34;&gt;1325&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;gotcha&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Gotcha!&lt;/span&gt; &lt;a href=&#34;#gotcha&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s another thing I had to navigate when setting this up.&lt;/p&gt;&#xA;&lt;p&gt;My &lt;code&gt;pivpn&lt;/code&gt; configuration sets the endpoint for my wireguard clients to &lt;code&gt;paynepride.com:&amp;lt;port forwarded to wireguard server&amp;gt;&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;What this means is that when I check the wireguard config for TrueNAS which is on my home network it resolves &lt;code&gt;paynepride.com&lt;/code&gt; to the server I have running my reverse proxy.&#xA;However! My reverse proxy is not responsible for my vpn traffic and so the traffic was just getting dropped - instead I needed to change the wireguard config just for my truenas box to piont to the local address of my vpn server.&#xA;This really threw me for a loop today but is just another reminder that if you have network problems it&amp;rsquo;s probably DNS&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;Give her the &amp;lsquo;ol reboot and now if I check &lt;code&gt;wg&lt;/code&gt; I should see some traffic on my wireguard tunnel!&lt;/p&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/truenas-wireguard.png&#34; alt=&#34;TrueNAS Wireguard&#34; title=&#34;TrueNAS and Wireguard&#34; /&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Pyclean</title>
    <id>https://pype.dev/pyclean/</id>
    <updated>2022-03-22T00:00:00Z</updated>
    <published>2022-03-22T00:00:00Z</published>
    <link href="https://pype.dev/pyclean/" rel="alternate" type="text/html"></link>
    <summary type="text">I like to keep my workspace clean and one thing that I don&#39;t personally love looking at is the directory that pops up after running some code. The files that...</summary>
    <content type="html">&lt;p&gt;I like to keep my workspace clean and one thing that I don&amp;rsquo;t personally love looking at is the &lt;code&gt;__pycache__&lt;/code&gt; directory that pops up after running some code.&#xA;The &lt;code&gt;*.pyc&lt;/code&gt; files that show up there are python bytecode and they are cached to make subsequent runs a tad faster.&#xA;My stuff never really needs this bonus speed boost and so I came across a neat tool called &lt;code&gt;pyclean&lt;/code&gt;!&lt;/p&gt;&#xA;&lt;h2 id=&#34;pyclean&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Pyclean&lt;/span&gt; &lt;a href=&#34;#pyclean&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;The easiest way (&lt;strong&gt;in my opinion&lt;/strong&gt;) to run &lt;code&gt;pyclean&lt;/code&gt; is to just use &lt;code&gt;pipx run&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sandbox/src  🌱 main 🗑️  ×3🛤️  ×2via 🐍 v3.8.11 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;sandbox&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;  took 9s&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ ls&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;abcmeta.py  __pycache__  python-print-align.py  system-monitor-psutils.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sandbox/src  🌱 main 🗑️  ×3🛤️  ×2via 🐍 v3.8.11 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;sandbox&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ pipx run pyclean .&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;⚠️  pyclean is already on your PATH and installed at /usr/bin/pyclean. Downloading and running anyway.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Cleaning directory .&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Total &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; files, &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; directories removed.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sandbox/src  🌱 main 🗑️  ×3🛤️  ×2via 🐍 v3.8.11 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;sandbox&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ ls&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;abcmeta.py  python-print-align.py  system-monitor-psutils.py&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;why-not-bash&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Why not bash?&lt;/span&gt; &lt;a href=&#34;#why-not-bash&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;You could accomplish something similar with &lt;code&gt;rm **/*.pyc&lt;/code&gt; or &lt;code&gt;find -n &#39;*.py?&#39; -delete&lt;/code&gt; but there&amp;rsquo;s a chance you&amp;rsquo;ll find something you don&amp;rsquo;t love gone.&#xA;Also this won&amp;rsquo;t help our poor Windows friends out there!&#xA;&lt;code&gt;pyclean&lt;/code&gt; is fully python so it&amp;rsquo;s OS independent.&lt;/p&gt;&#xA;&lt;h2 id=&#34;credits&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Credits!&lt;/span&gt; &lt;a href=&#34;#credits&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/bittner/pyclean&#34;&gt;repo&lt;/a&gt;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Psutil-01</title>
    <id>https://pype.dev/psutils-01/</id>
    <updated>2022-03-16T00:00:00Z</updated>
    <published>2022-03-16T00:00:00Z</published>
    <link href="https://pype.dev/psutils-01/" rel="alternate" type="text/html"></link>
    <summary type="text">Mike Driscoll has been posting some awesome posts about lately. I&#39;m interested in making my own system monitoring dashboard now using this library. I don&#39;t...</summary>
    <content type="html">&lt;p&gt;&lt;a href=&#34;https://twitter.com/driscollis&#34;&gt;Mike Driscoll&lt;/a&gt; has been posting some awesome posts about &lt;code&gt;psutil&lt;/code&gt; lately.&#xA;I&amp;rsquo;m interested in making my own system monitoring dashboard now using this library.&#xA;I don&amp;rsquo;t expect it to compete with Netdata or Glances but it&amp;rsquo;ll just be for fun to see how Python can solve this problem!&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Repo coming soon&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;example-code&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Example code:&lt;/span&gt; &lt;a href=&#34;#example-code&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s a short snippit to get used/available/total RAM and disk space (on partitions that you probably care about)&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;psutil&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;socket&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;System Memory used: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;psutil&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;virtual_memory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;used&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;//&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1024&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;**&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; GB&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;System Memory available: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;psutil&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;virtual_memory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;available&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;//&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1024&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;**&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; GB&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;System Memory total: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;psutil&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;virtual_memory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;//&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1024&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;**&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; GB&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Hostname: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;socket&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;gethostname&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;partitions&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;psutil&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;disk_partitions&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;part&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;partitions&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;mnt&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;part&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mountpoint&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;snap&amp;#34;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mnt&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;or&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;boot&amp;#34;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mnt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;continue&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;disk&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;psutil&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;disk_usage&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mnt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Usage at &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mnt&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; on &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;part&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;device&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;disk&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;used&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;//&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1024&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;**&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; GB&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Free at &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mnt&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; on &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;part&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;device&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;disk&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;free&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;//&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1024&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;**&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;GB&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Total at &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mnt&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; on &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;part&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;device&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;disk&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;//&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1024&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;**&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;GB&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;&#xA;&lt;p&gt;Bonus Ipython tip! Save this to a script called my_script.py and in Ipython you can %run -m my_script to run it!&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;project ↪ main v3.8.11 ipython&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ %run -m system-monitor-psutils&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;System Memory used: &lt;span class=&#34;m&#34;&gt;25&lt;/span&gt; GB&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;System Memory available: &lt;span class=&#34;m&#34;&gt;5&lt;/span&gt; GB&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;System Memory total: &lt;span class=&#34;m&#34;&gt;31&lt;/span&gt; GB&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Hostname: ryzen-3600x&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Usage at / on /dev/nvme1n1p2: &lt;span class=&#34;m&#34;&gt;81&lt;/span&gt; GB&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Free at / on /dev/nvme1n1p2: &lt;span class=&#34;m&#34;&gt;351&lt;/span&gt; GB&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Total at / on /dev/nvme1n1p2: &lt;span class=&#34;m&#34;&gt;456&lt;/span&gt; GB&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Mu</title>
    <id>https://pype.dev/mu/</id>
    <updated>2022-03-15T00:00:00Z</updated>
    <published>2022-03-15T00:00:00Z</published>
    <link href="https://pype.dev/mu/" rel="alternate" type="text/html"></link>
    <summary type="text">If you work with a template for several projects then you might sometimes need to do the same action across all repos. A good example of this is updating a...</summary>
    <content type="html">&lt;p&gt;If you work with a template for several projects then you might sometimes need to do the same action across all repos.&#xA;A good example of this is updating a package in &lt;code&gt;requirements.txt&lt;/code&gt; in every project, or refactoring a common module.&#xA;If you have several repos to do this across then it can be time consuming&amp;hellip; enter &lt;code&gt;mu-repo&lt;/code&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;mu&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Mu&lt;/span&gt; &lt;a href=&#34;#mu&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://fabioz.github.io/mu-repo/&#34;&gt;mu-repo&lt;/a&gt; is an awesome cli tool for working with multiple git repositories at the same time.&#xA;There are several things you can do:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;code&gt;mu status&lt;/code&gt; will give you the &lt;code&gt;git status&lt;/code&gt; of every registered repo (see below)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;mu sh&lt;/code&gt; will let you execute system level commands in every repo&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;mu stash&lt;/code&gt; will stash all changes across all registered repos&lt;/li&gt;&#xA;&lt;li&gt;There&amp;rsquo;s literally a ton more but these are some handy ones&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;registration&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Registration&lt;/span&gt; &lt;a href=&#34;#registration&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;&lt;code&gt;mu&lt;/code&gt; tracks its own &lt;code&gt;groups&lt;/code&gt;, and there is a default group when no particular one is active.&#xA;It&amp;rsquo;s as simple as &lt;code&gt;mu register proj1 prog2 ...&lt;/code&gt; to get repos registered&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ mu register proj1 proj2&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Repository: proj1 registered&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Repository: proj2 registered&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ mu status&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  proj1 : git status&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    On branch main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    No commits yet&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    Untracked files:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;use &lt;span class=&#34;s2&#34;&gt;&amp;#34;git add &amp;lt;file&amp;gt;...&amp;#34;&lt;/span&gt; to include in what will be committed&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    requirements.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    nothing added to commit but untracked files present &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;use &lt;span class=&#34;s2&#34;&gt;&amp;#34;git add&amp;#34;&lt;/span&gt; to track&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  proj2 : git status&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    On branch main&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    No commits yet&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    Changes to be committed:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;use &lt;span class=&#34;s2&#34;&gt;&amp;#34;git rm --cached &amp;lt;file&amp;gt;...&amp;#34;&lt;/span&gt; to unstage&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    new file:   requirements.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;working-with-mu&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Working with mu&lt;/span&gt; &lt;a href=&#34;#working-with-mu&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;As you can see above I have two projects each with a &lt;code&gt;requirements.txt&lt;/code&gt; added but not committed yet.&#xA;Using &lt;code&gt;mu&lt;/code&gt; I can stage this change across both repos at once.&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ mu add requirements.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  proj1 : git add requirements.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  proj2 : git add requirements.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then as you might imagine, I can make the commit in each repo&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ mu commit -m &lt;span class=&#34;s2&#34;&gt;&amp;#34;Add requirements.txts&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  proj1 : git commit -m Add requirements.txts&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;main &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;root-commit&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; 18376d7&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; Add requirements.txts&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; file changed, &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; insertion&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;+&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    create mode &lt;span class=&#34;m&#34;&gt;100644&lt;/span&gt; requirements.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  proj2 : git commit -m Add requirements.txts&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;main &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;root-commit&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; 18376d7&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; Add requirements.txts&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; file changed, &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; insertion&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;+&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    create mode &lt;span class=&#34;m&#34;&gt;100644&lt;/span&gt; requirements.txt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;mu-groups&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;mu groups&lt;/span&gt; &lt;a href=&#34;#mu-groups&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;The other thing I got a lot of use out of recently was &lt;code&gt;mu&lt;/code&gt;&amp;rsquo;s groups.&#xA;At work I have about 40 repos cloned that are all based on the same kedro pipeline template.&#xA;Some of these projects have been deprecated.&#xA;I also have several more repos that are not kedro template - custom libraries or something.&#xA;&lt;code&gt;group&lt;/code&gt; let me utilize &lt;code&gt;mu&lt;/code&gt; across different groups of repos.&lt;/p&gt;&#xA;&lt;p&gt;Say &lt;code&gt;proj2&lt;/code&gt; is a deprecated project that I don&amp;rsquo;t need to worry about making changes to anymore.&#xA;I don&amp;rsquo;t just have to unregister it, instead I can make a group called &amp;ldquo;active&amp;rdquo; and register &lt;code&gt;proj1&lt;/code&gt; in that group&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ mu group add active --empty&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;~/personal&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ mu group add deprecated --empty&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;~/personal&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ mu group&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  active&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;* deprecated&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;*&lt;/code&gt; tells me which group is active.&#xA;The &lt;code&gt;--empty&lt;/code&gt; flag tells &lt;code&gt;mu&lt;/code&gt; to not add all registered repos to that group.&#xA;If I don&amp;rsquo;t want to use any groups then &lt;code&gt;mu group reset&lt;/code&gt; will go back to the default group with all registered repos.&lt;/p&gt;&#xA;&lt;p&gt;With groups I can register only the repos that I want to be working across in their own group and not worry about affecting other repos with my batch changes!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Wireguard</title>
    <id>https://pype.dev/wireguard/</id>
    <updated>2022-03-12T00:00:00Z</updated>
    <published>2022-03-12T00:00:00Z</published>
    <link href="https://pype.dev/wireguard/" rel="alternate" type="text/html"></link>
    <summary type="text">Virtual Private Networks are a big deal, and this shouldn&#39;t be considered anything even close to a guide on using them. Here are just my notes and some setup...</summary>
    <content type="html">&lt;h2 id=&#34;vpn&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;VPN&lt;/span&gt; &lt;a href=&#34;#vpn&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Virtual Private Networks are a big deal, and this shouldn&amp;rsquo;t be considered anything even close to a guide on using them.&#xA;Here are just my notes and some setup for how I use &lt;a href=&#34;https://www.wireguard.com/&#34;&gt;wireguard&lt;/a&gt; at home.&lt;/p&gt;&#xA;&lt;h2 id=&#34;wireguard&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Wireguard&lt;/span&gt; &lt;a href=&#34;#wireguard&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Wireguard is an awesome peer-to-peer VPN tunnel that makes it really easy for me to get into my home network when I&amp;rsquo;m out and about.&#xA;My main reasons for this are 1. I don&amp;rsquo;t trust public wi-fi and 2. I want to use pi-hole for ad blocking when I&amp;rsquo;m not at home&lt;/p&gt;&#xA;&lt;p&gt;Wireguard can be configured as a &amp;ldquo;peer-to-site&amp;rdquo; VPN tunnel as well.&#xA;My vpn setup let&amp;rsquo;s me jump to various machines on my network from anywhere!&lt;/p&gt;&#xA;&lt;p&gt;I use &lt;a href=&#34;https://pivpn.io/&#34;&gt;pivpn&lt;/a&gt; in a VM that&amp;rsquo;s already running &lt;code&gt;pi-hole&lt;/code&gt; to host my wireguard server.&#xA;It&amp;rsquo;s super easy to setup just by following the instructions on the pivpn site.&lt;/p&gt;&#xA;&lt;p&gt;The reason I like it is that I have a nice &lt;code&gt;cli&lt;/code&gt; for managing wireguard configs.&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;dumbledore@pihole-vpn:~$ pivpn&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;::: Control all PiVPN specific functions!&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;:::&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;::: Usage: pivpn &amp;lt;command&amp;gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;option&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;:::&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;::: Commands:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;:::    -a, add              Create a client conf profile&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;:::    -c, clients          List any connected clients to the server&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;:::    -d, debug            Start a debugging session &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; having trouble&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;:::    -l, list             List all clients&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;:::   -qr, qrcode           Show the qrcode of a client &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; use with the mobile app&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;:::    -r, remove           Remove a client&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;:::  -off, off              Disable a user&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;:::   -on, on               Enable a user&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;:::    -h, &lt;span class=&#34;nb&#34;&gt;help&lt;/span&gt;             Show this &lt;span class=&#34;nb&#34;&gt;help&lt;/span&gt; dialog&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;:::    -u, uninstall        Uninstall pivpn from your system!&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;:::   -up, update           Updates PiVPN Scripts&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;:::   -bk, backup           Backup VPN configs and user profiles&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;When I&amp;rsquo;m ready to add a new client to my &lt;code&gt;wg&lt;/code&gt; network, it&amp;rsquo;s as easy as &lt;code&gt;pivpn add&lt;/code&gt; and follow the instructions.&#xA;The easiest part here is that you&amp;rsquo;ll be given a QR code in the terminal that you can just scan with the client (like a smart phone) and you&amp;rsquo;ll have your wireguard config handled by the app (oh right, download the wireguard app) in no time!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Git-Worktrees-01</title>
    <id>https://pype.dev/git-worktrees-01/</id>
    <updated>2022-03-11T00:00:00Z</updated>
    <published>2022-03-11T00:00:00Z</published>
    <link href="https://pype.dev/git-worktrees-01/" rel="alternate" type="text/html"></link>
    <summary type="text">Hopefully if you write code you are using git, if not go learn the basics of , , , and / like... right now.</summary>
    <content type="html">&lt;h2 id=&#34;git&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Git&lt;/span&gt; &lt;a href=&#34;#git&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Hopefully if you write code you are using git, if not go learn the basics of &lt;code&gt;commit&lt;/code&gt;, &lt;code&gt;pull&lt;/code&gt;, &lt;code&gt;push&lt;/code&gt;, and &lt;code&gt;pull request&lt;/code&gt;/&lt;code&gt;merge request&lt;/code&gt; like&amp;hellip; right now.&lt;/p&gt;&#xA;&lt;p&gt;Assuming you are at least familiar with git then you probably work the same way I have since I&amp;rsquo;ve been using it.&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;clone or initialize a repo&lt;/li&gt;&#xA;&lt;li&gt;checkout a branch, &lt;code&gt;git checkout -b my-feature&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;work on &lt;code&gt;my-feature&lt;/code&gt; and when ready open a PR into &lt;code&gt;main&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;git pull main&lt;/code&gt; then &lt;code&gt;git checkout -b another-feature&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;etc&amp;hellip;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;What if you need to switch between branches for some reason? Often I&amp;rsquo;m jumping into projects with my co-workers left and right, and I&amp;rsquo;ll have changes that I&amp;rsquo;m either working on or exploring for them.&#xA;When it&amp;rsquo;s time to switch branches I think there&amp;rsquo;s more elegant ways than this but I&amp;rsquo;ve always done this:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;code&gt;stash&lt;/code&gt; the current changes&lt;/li&gt;&#xA;&lt;li&gt;checkout out the relevant branch&lt;/li&gt;&#xA;&lt;li&gt;helped out&lt;/li&gt;&#xA;&lt;li&gt;re-checkout my original branch&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;pop&lt;/code&gt; the &lt;code&gt;stash&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Now, that&amp;rsquo;s not awful but I think &lt;code&gt;worktrees&lt;/code&gt; will make this nicer for a few reasons!&lt;/p&gt;&#xA;&lt;h2 id=&#34;worktrees&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Worktrees&lt;/span&gt; &lt;a href=&#34;#worktrees&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Worktrees are linked branches that have their own directories somewhere on your computer.&#xA;To checkout a branch you don&amp;rsquo;t have to worry about stashing any changes, you just &lt;code&gt;cd&lt;/code&gt; into the directory of that branch.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The branch can be literally anywhere - it doesn&amp;rsquo;t have to be in the repo folder&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h2 id=&#34;use-case&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Use Case&lt;/span&gt; &lt;a href=&#34;#use-case&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve seen ThePrimeagean argue for worktrees for several reasons, see a YT video &lt;a href=&#34;https://www.youtube.com/watch?v=2uEqYw-N8uE&#34;&gt;here&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;m entirely in Python at the moment, or working with projects that dont&amp;rsquo; have that kind of requirement (ie. this website).&#xA;My reason for wanting worktrees is 3 fold.&lt;/p&gt;&#xA;&lt;h3 id=&#34;files-that-could-have-been-gitignored-but-ain-t&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Files that could have been gitignored but ain’t&lt;/span&gt; &lt;a href=&#34;#files-that-could-have-been-gitignored-but-ain-t&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;I have a &lt;code&gt;.envrc&lt;/code&gt; I put in every project, but it&amp;rsquo;s not gitignored for reasons that aren&amp;rsquo;t relevant right now&amp;hellip;&#xA;If I switch branches I&amp;rsquo;ll stash everything I have at the time, including my .envrc, but then if I forget to pop the stash and I move on and come back then my environment isn&amp;rsquo;t active and I have to go find the stash, pop it, cd out, and then back in and honestly&amp;hellip;. that sucks.&#xA;Worktrees will let me have the .envrc in every branch, and if I checkout or switch to a new one, my personal branch is unaffected.&lt;/p&gt;&#xA;&lt;h3 id=&#34;symlinks&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Symlinks&lt;/span&gt; &lt;a href=&#34;#symlinks&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;In my team&amp;rsquo;s &lt;a href=&#34;https://kedro.readthedocs.io/en/stable/01_introduction/01_introduction.html&#34;&gt;Kedro&lt;/a&gt; workflow we keep a specific directory, the &lt;code&gt;conf&lt;/code&gt; directory at a different spot than the Kedro team has in their templates (the why is outside the scope here).&#xA;The way I preserve every kedro utility for my own benefit is to symlink our &lt;code&gt;conf&lt;/code&gt; to where the Kedro template expects it to be.&#xA;But then everytime I stash changes I lose that symlink so I either just don&amp;rsquo;t have it for the time being or I recreate it which is a hassle&#xA;Worktrees will let me have that present and persistent on all my branches at once.&lt;/p&gt;&#xA;&lt;h3 id=&#34;foo&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Foo&lt;/span&gt; &lt;a href=&#34;#foo&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;Because why not!? This workflow feels future-proof, and if my toolset changes down the line then having this worktree centric workflow might be helpful and I&amp;rsquo;m just prepping for that possibility!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Abstract-Base-Class</title>
    <id>https://pype.dev/abstract-base-class/</id>
    <updated>2022-03-09T00:00:00Z</updated>
    <published>2022-03-09T00:00:00Z</published>
    <link href="https://pype.dev/abstract-base-class/" rel="alternate" type="text/html"></link>
    <summary type="text">I don&#39;t do a lot of OOP currently, but I have been on a few heavy OOP projects and this and from would&#39;ve been super nice to know about!</summary>
    <content type="html">&lt;h2 id=&#34;abcmeta&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;ABCMeta&lt;/span&gt; &lt;a href=&#34;#abcmeta&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I don&amp;rsquo;t do a lot of OOP currently, but I have been on a few heavy OOP projects and this &lt;code&gt;ABCMeta&lt;/code&gt; and &lt;code&gt;abstractmethod&lt;/code&gt; from &lt;code&gt;abc&lt;/code&gt; would&amp;rsquo;ve been super nice to know about!&lt;/p&gt;&#xA;&lt;p&gt;If you are creating a library with classes that you expect your users to extend, but you want to ensure that any extension has explicit methods defined then this is for you!.&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;abc&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ABCMeta&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;abstractmethod&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Family&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;metaclass&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ABCMeta&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nd&#34;&gt;@abstractmethod&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;get_dad&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;Any extension of the Family class must implement a `get_dad` method&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;MyFamily&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Family&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;pass&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If I try to instantiate &lt;code&gt;MyFamily&lt;/code&gt; I will not be allowed:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;❯&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;my_fam&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;MyFamily&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;╭───────────────────────────────&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Traceback&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;most&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;recent&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;call&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;last&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;────────────────────────────────╮&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ipython&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ecb8e21ce815&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;module&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;                                                     &lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;╰──────────────────────────────────────────────────────────────────────────────────────────────────╯&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;ne&#34;&gt;TypeError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Can&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;t instantiate abstract class MyFamily with abstract methods get_dad&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/py-abc-meta.png&#34; alt=&#34;abcmetadata&#34; title=&#34;ABC Metadata&#34; /&gt;&#xA;&lt;p&gt;In order for me to extend &lt;code&gt;Family&lt;/code&gt; I have to implement the method &lt;code&gt;get_dad&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;MyFamily&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Family&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;get_dad&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Me&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now everything works as expected and I can sleep well knowing no one can extend my base class without creating methods I know they need.&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;my_fam&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;MyFamily&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;my_fam&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get_dad&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Me&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Python-F-String-Align</title>
    <id>https://pype.dev/python-f-string-align/</id>
    <updated>2022-03-08T00:00:00Z</updated>
    <published>2022-03-08T00:00:00Z</published>
    <link href="https://pype.dev/python-f-string-align/" rel="alternate" type="text/html"></link>
    <summary type="text">I am personally trying to use instead of in all of my code, however I learned from [@Python-Hub] that you can align printouts using with -strings!.</summary>
    <content type="html">&lt;p&gt;I am personally trying to use &lt;code&gt;logger&lt;/code&gt; instead of &lt;code&gt;print&lt;/code&gt; in all of my code,&#xA;however I learned from [@Python-Hub] that you can align printouts using &lt;code&gt;print&lt;/code&gt; with &lt;code&gt;f&lt;/code&gt;-strings!.&lt;/p&gt;&#xA;&lt;p&gt;This little python script shows how options in the &lt;code&gt;f&lt;/code&gt;-string can format the printout.&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;random&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;variables&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Foo Bar Baz Bing&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;split&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;scores&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;random&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sample&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;variables&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;*&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;30&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;With &amp;#39;varable&amp;#39; left aligned&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;varable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;score&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;zip&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;variables&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;scores&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;varable&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;lt;10&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; | &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;score&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;*&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;30&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;With &amp;#39;varable&amp;#39; right aligned&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;varable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;score&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;zip&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;variables&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;scores&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;varable&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;gt;15&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; | &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;score&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;*&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;30&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;With &amp;#39;varable&amp;#39; center aligned&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;varable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;score&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;zip&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;variables&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;scores&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;varable&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;^5&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; | &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;score&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/py-print-align.png&#34; alt=&#34;pyprintalign&#34; title=&#34;Align f-string printing&#34; /&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Python-Builtin-Calendar</title>
    <id>https://pype.dev/python-builtin-calendar/</id>
    <updated>2022-03-08T00:00:00Z</updated>
    <published>2022-03-08T00:00:00Z</published>
    <link href="https://pype.dev/python-builtin-calendar/" rel="alternate" type="text/html"></link>
    <summary type="text">I almost exclusively use Python for my job and have been eye-balls deep in it for almost 5 years but I really lack in-depth knowledge of builtins. I recently...</summary>
    <content type="html">&lt;h2 id=&#34;being-lazy&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Being lazy&lt;/span&gt; &lt;a href=&#34;#being-lazy&#34; class=&#34;heading-anchor&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;I almost exclusively use Python for my job and have been eye-balls deep in it for almost 5 years but I really lack in-depth knowledge of builtins.&#xA;I recently learned of an awesome builtin called &lt;code&gt;calendar&lt;/code&gt;  that has way more than I know about for sure but I&amp;rsquo;m glad I know it&amp;rsquo;s here now!&lt;/p&gt;&#xA;&lt;p&gt;I only needed it because I was too lazy to hard code the 7 weekdays into my module but it turns out there&amp;rsquo;s a lot of useful things like &lt;code&gt;calendar.isleap()&lt;/code&gt;!&lt;/p&gt;&#xA;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/builtin-calendar.png&#34; alt=&#34;builtin&#34; title=&#34;Python&#39;s builtin calendar&#34; /&gt;&#xA;## Future use&#xA;&lt;p&gt;I&amp;rsquo;m not exactly sure what will come my way where &lt;code&gt;calendar&lt;/code&gt; will be super relevant but like anything, I&amp;rsquo;m just glad to know it exists for when the time arises!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Dataframe-Memory-Usage</title>
    <id>https://pype.dev/dataframe-memory-usage/</id>
    <updated>2022-03-07T00:00:00Z</updated>
    <published>2022-03-07T00:00:00Z</published>
    <link href="https://pype.dev/dataframe-memory-usage/" rel="alternate" type="text/html"></link>
    <summary type="text">I have often wanted to dive into memory usage for pandas DataFrames when it comes to cloud deployment. If I have a python process running on a server at home...</summary>
    <content type="html">&lt;p&gt;I have often wanted to dive into memory usage for pandas DataFrames when it comes to cloud deployment.&#xA;If I have a python process running on a server at home I can use &lt;code&gt;glances&lt;/code&gt; or a number of other tools to diagnose a memory issue&amp;hellip;&#xA;However at work I normally deploy dockerized processes on AWS Batch and it&amp;rsquo;s much more challenging to get info on the dockerized process without more AWS integration that my team isn&amp;rsquo;t quite ready for.&#xA;So TIL that I can get some of the info I want from pandas directly!&lt;/p&gt;&#xA;&lt;h1 id=&#34;dataframe-info&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;DataFrame.info()&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;I didn&amp;rsquo;t realize that &lt;code&gt;df.info()&lt;/code&gt; was able to give me more info than just dtypes and some summary stats&amp;hellip;&#xA;There is a kwarg &lt;code&gt;memory_usage&lt;/code&gt; that can configure what you need to get back, so &lt;code&gt;df.memory_usage=&amp;quot;deep&amp;quot;&lt;/code&gt; will give you how much RAM any given DataFrame is using!&#xA;Amazing tool for finding issues with joins or renegade source data files.&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read_csv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;cars.csv&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;memory_usage&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;deep&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;img src=&#34;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/blog-media/df-memory-usage.png&#34; alt=&#34;DataFrame Memory Usage&#34; title=&#34;DataFrame Memory Usage&#34; /&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Adblock-Coverage</title>
    <id>https://pype.dev/adblock-coverage/</id>
    <updated>2022-03-07T00:00:00Z</updated>
    <published>2022-03-07T00:00:00Z</published>
    <link href="https://pype.dev/adblock-coverage/" rel="alternate" type="text/html"></link>
    <summary type="text">I run pi-hole at home for ad blocking and some internal DNS/DHCP handling.</summary>
    <content type="html">&lt;p&gt;I run pi-hole at home for ad blocking and some internal DNS/DHCP handling.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;pi hole posts on the way&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;One thing I&amp;rsquo;ve never put too much thought in is asking &amp;ldquo;how well am I doing at blocking?&amp;rdquo;&#xA;There&amp;rsquo;s lots of ways to measure that depending on what you care about but I just learned of &lt;a href=&#34;https://d3ward.github.io/toolz/adblock&#34;&gt;adblock tester&lt;/a&gt;.&#xA;It&amp;rsquo;s awesome and gave me a quick glimpse into how my pi-hole is performing on keeping my webpages clean and my DNS history private!&lt;/p&gt;&#xA;&lt;p&gt;Credits to &lt;a href=&#34;https://github.com/d3ward/toolz&#34;&gt;d3ward&lt;/a&gt; for the awesome tool!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Webservers-And-Indexes</title>
    <id>https://pype.dev/webservers-and-indexes/</id>
    <updated>2022-03-06T00:00:00Z</updated>
    <published>2022-03-06T00:00:00Z</published>
    <link href="https://pype.dev/webservers-and-indexes/" rel="alternate" type="text/html"></link>
    <summary type="text">I host a lot of services in my homelab, but they&#39;re mostly dockerized applications so I have never had to care much about how content gets served up. Today I...</summary>
    <content type="html">&lt;p&gt;I host a lot of services in my homelab, but they&amp;rsquo;re mostly dockerized applications so I have never had to care much about how content gets served up.&#xA;Today I had several little concepts click into place regarding webservers, and it was a similar experience to when I started homelabing and didn&amp;rsquo;t know what a &amp;ldquo;server&amp;rdquo; was in the first place.&lt;/p&gt;&#xA;&lt;h1 id=&#34;servers&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Servers&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;A &amp;ldquo;server&amp;rdquo; can have a lot of different meanings but specifically in my world it was a physical server, like my PowerEdge R610 which acts as my main &amp;ldquo;home server&amp;rdquo;.&#xA;But then on my server, I have other servers&amp;hellip; Jellyfin is my main media server - but that&amp;rsquo;s obviously not a hardware thing, that&amp;rsquo;s software.&#xA;This is certainly not a groundbreaking thing but it was a tiny piece to the puzzle that I was missing&amp;hellip; that &amp;ldquo;server&amp;rdquo; is highly contextual.&lt;/p&gt;&#xA;&lt;h1 id=&#34;webservers&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Webservers&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;Something that confused the heck out of me when I first started down the road of having a server was what a webserver even was&amp;hellip;&#xA;I always thought the &amp;ldquo;webserver&amp;rdquo; was just &amp;ldquo;a server that hosts a website&amp;rdquo;&amp;hellip; and yes, that&amp;rsquo;s true, but also it wasn&amp;rsquo;t true in how I understood &amp;ldquo;server&amp;rdquo;.&#xA;It turns out that across my 40-odd dockerized services I have at home that I must have about 40-odd web servers running, each docker container is spinning up its own!&lt;/p&gt;&#xA;&lt;p&gt;So something I have wanted to do for a long time is put my theology notes online for my small group to access whenever they might want&amp;hellip; it doesn&amp;rsquo;t need to be fancy or anything.&#xA;My issue was not knowing what to even Google. I tried &amp;ldquo;How to serve up static html&amp;rdquo; but that kind of search is for people who know what a &amp;ldquo;static&amp;rdquo; site is - I am not one of those people.&#xA;I kept running across nginx and apache things, wordpress and other website building tools, etc.&#xA;In fact I only recently learned that JavaScript assets cann still be considered static so I am a complete baby in the web-dev space.&lt;/p&gt;&#xA;&lt;p&gt;What I really wanted was just a simple landing page with a link to each of my &amp;ldquo;posts&amp;rdquo; which are in the form of a single html file each that I can easily export from my tiddlywiki (I have a post about tiddlywiki &lt;a href=&#34;/tiddly-wiki&#34;&gt;here&lt;/a&gt;)&lt;/p&gt;&#xA;&lt;p&gt;The first win &lt;code&gt;python -m http.server&lt;/code&gt; right in the directory I kept my html files in and that got me what I wanted functionally.&#xA;But then I wanted just a hair more organization&amp;hellip;&#xA;I started looking for a way to dynamically generate an index for a directory of html files but again the verbiage of that Google search just wasn&amp;rsquo;t helping me - I didn&amp;rsquo;t want anything complicated and I knew that what I wanted had to be easy&amp;hellip;&lt;/p&gt;&#xA;&lt;h1 id=&#34;the-index&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;The Index&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;Luckily I randomly came across a SO that mentioned a Linux utility called &lt;code&gt;tree&lt;/code&gt; which does exactly what I wanted!&lt;/p&gt;&#xA;&lt;p&gt;See my TIL on &lt;code&gt;tree&lt;/code&gt; &lt;a href=&#34;&#39;/tree&#39;&#34;&gt;here&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;So now it goes like this:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Take notes on X in my tiddlywiki&lt;/li&gt;&#xA;&lt;li&gt;Export that tiddler to a html file&lt;/li&gt;&#xA;&lt;li&gt;Put that html file into a &lt;code&gt;notes&lt;/code&gt; folder in my github repo for small group notes&lt;/li&gt;&#xA;&lt;li&gt;Use &lt;code&gt;tree&lt;/code&gt; to generate an &lt;code&gt;index.html&lt;/code&gt; of each of those files in the &lt;code&gt;notes&lt;/code&gt; directory&lt;/li&gt;&#xA;&lt;li&gt;Use &lt;code&gt;python -m http.server&lt;/code&gt; to start a web server that lands me at the &lt;code&gt;index.html&lt;/code&gt; and now I can click through to any post!&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;It&amp;rsquo;s not fancy but it&amp;rsquo;s functional&amp;hellip;&#xA;This site/blog is built with markdown and &lt;a href=&#34;https://www.markata.dev&#34;&gt;markata&lt;/a&gt; and I wanted way more functionality in my tech notes.&#xA;But for this simple use case I learned a ton about &lt;em&gt;how&lt;/em&gt; content gets served up on a webpage and my small group benefits from the easy access as well!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Tree</title>
    <id>https://pype.dev/tree/</id>
    <updated>2022-03-06T00:00:00Z</updated>
    <published>2022-03-06T00:00:00Z</published>
    <link href="https://pype.dev/tree/" rel="alternate" type="text/html"></link>
    <summary type="text">I wanted a quick way to generate an for a directory of html files that grows by 1 or 2 files a week. I don&#39;t know any html (the files are exports from my...</summary>
    <content type="html">&lt;p&gt;I wanted a quick way to generate an &lt;code&gt;index.html&lt;/code&gt; for a directory of html files that grows by 1 or 2 files a week.&#xA;I don&amp;rsquo;t know any html (the files are exports from my &lt;a href=&#34;/tiddly-wiki&#34;&gt;tiddlywiki&lt;/a&gt;)&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;tree&lt;/code&gt; is just the answer.&lt;/p&gt;&#xA;&lt;p&gt;Say I have a file structure like this:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;./html-files&#xA;├── file1.html&#xA;└── file2.html&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;To generate a barebones simple &lt;code&gt;index.html&lt;/code&gt; we can use tree as follows:&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;tree ./html-files -H &amp;quot;.&amp;quot; -L 1 -P &amp;quot;*.html&amp;quot;&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;and get the following:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;html&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;meta&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;http-equiv&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Content-Type&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;text/html; charset=UTF-8&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;meta&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Author&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Made by &amp;#39;tree&amp;#39;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;meta&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;GENERATOR&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;$Version: $ tree v1.8.0 (c) 1996 - 2018 by Steve Baker, Thomas Moore, Francesc Rocher, Florian Sesser, Kyosuke Tokoro $&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;Directory Tree&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;style&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;text/css&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;o&#34;&gt;&amp;lt;!&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;--&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;BODY&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;font-family&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ariel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;monospace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;sans-serif&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;P&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;font-weight&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;normal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;font-family&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ariel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;monospace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;sans-serif&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;black&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;background-color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;transparent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;B&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;font-weight&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;normal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;black&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;background-color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;transparent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;visited&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;font-weight&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;normal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;text-decoration&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;none&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;background-color&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;transparent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;margin&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;padding&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;display&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;inline&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;link&lt;/span&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;font-weight&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;normal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;text-decoration&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;none&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;margin&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;padding&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;display&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;inline&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;hover&lt;/span&gt;   &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;color&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;#000000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;font-weight&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;normal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;text-decoration&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;underline&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;background-color&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;yellow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;margin&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;padding&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;display&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;inline&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;active&lt;/span&gt;  &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;color&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;#000000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;font-weight&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;normal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;background-color&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;transparent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;margin&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;padding&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;px&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;display&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;inline&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;VERSION&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;font-size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;small&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;font-family&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;arial&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;sans-serif&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;NORM&lt;/span&gt;  &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;black&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;  &lt;span class=&#34;k&#34;&gt;background-color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;transparent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;FIFO&lt;/span&gt;  &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;purple&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;background-color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;transparent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;CHAR&lt;/span&gt;  &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;yellow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;background-color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;transparent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;DIR&lt;/span&gt;   &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;blue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;   &lt;span class=&#34;k&#34;&gt;background-color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;transparent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;BLOCK&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;yellow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;background-color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;transparent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;LINK&lt;/span&gt;  &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;aqua&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;   &lt;span class=&#34;k&#34;&gt;background-color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;transparent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;SOCK&lt;/span&gt;  &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;fuchsia&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;background-color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;transparent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;EXEC&lt;/span&gt;  &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;green&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;  &lt;span class=&#34;k&#34;&gt;background-color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;transparent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;--&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;style&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;body&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;h1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;Directory Tree&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;h1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;href&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;.&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;br&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        ├── &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;href&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;./file1.html&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;file1.html&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;br&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        └── &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;href&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;./file2.html&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;file2.html&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;br&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;br&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;br&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0 directories, 2 files&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;br&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;br&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;hr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;p&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;VERSION&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                 tree v1.8.0 © 1996 - 2018 by Steve Baker and Thomas Moore &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;br&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                 HTML output hacked and copyleft © 1998 by Francesc Rocher &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;br&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                 JSON output hacked and copyleft © 2014 by Florian Sesser &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;br&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                 Charsets / OS/2 support © 2001 by Kyosuke Tokoro&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;body&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;html&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;which &lt;a href=&#34;/tree-index-example.html&#34;&gt;looks like this&lt;/a&gt; when you serve it up with &lt;code&gt;python -m http.server&lt;/code&gt;&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Traefik</title>
    <id>https://pype.dev/traefik/</id>
    <updated>2022-03-06T00:00:00Z</updated>
    <published>2022-03-06T00:00:00Z</published>
    <link href="https://pype.dev/traefik/" rel="alternate" type="text/html"></link>
    <summary type="text">If you don&#39;t know about traefik and you need a reverse-proxy then you might want to check it out. I used to use nginx for my reverse proxy but the config was...</summary>
    <content type="html">&lt;h1 id=&#34;traefik&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Traefik&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;If you don&amp;rsquo;t know about &lt;a href=&#34;https://doc.traefik.io/traefik/&#34;&gt;traefik&lt;/a&gt; and you need a reverse-proxy then you might want to check it out.&#xA;I used to use nginx for my reverse proxy but the config was over my head, and once it was working I was afraid to touch it.&#xA;Traefik brings a lot to the table, my main uses are reverse proxy and ip whitelisting, but it&amp;rsquo;s doing even more under the hood that I don&amp;rsquo;t have a full-grasp of yet.&lt;/p&gt;&#xA;&lt;p&gt;I like Traefik a lot because once I get some basic config up it&amp;rsquo;s incredibly easy to add services into my homelab whether they run on my primary server or not.&#xA;This will not be exhaustive but I&amp;rsquo;ll outline my simple setup process of traefik and how I add services whether they are in docker or not.&lt;/p&gt;&#xA;&lt;h1 id=&#34;docker&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Docker&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;In 2022 I&amp;rsquo;m still a docker fan-boy and I run my traefik instance in a docker container.&#xA;This isn&amp;rsquo;t necessary but I love the portability since my homelab is very dynamic at the moment.&#xA;And even if it wasn&amp;rsquo;t I&amp;rsquo;d still want to keep traefik in docker because deployment and updating are just so flipping easy&lt;/p&gt;&#xA;&lt;p&gt;A simple docker-compose file for traefik might look like this:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;traefik&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;traefik:v2.4&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;network_mode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;host&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;volumes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;docker-data/traefik/traefik.toml:/etc/traefik/traefik.toml:ro&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;docker-data/traefik/config.yml:/etc/traefik/config.yml:ro&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;docker-data/traefik/letsencrypt:/letsencrypt:rw&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;/var/run/docker.sock:/var/run/docker.sock:ro&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# for auto-discovery&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;env&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;{{ traefik_environment_variables }}&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;restart_policy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;unless-stopped&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;memory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;1g&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;ansible-deployment&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Ansible deployment&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;&lt;strong&gt;I plan to have more on my homelab and Ansible on this site eventually&amp;hellip;&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;I use Ansible to deploy most of my services at home, including traefik. My main homelab repo is &lt;a href=&#34;https://github.com/nicpayne713/ansible-nas&#34;&gt;here&lt;/a&gt; which is a fork of &lt;a href=&#34;https://github.com/davestephens/ansible-nas&#34;&gt;Ansible NAS&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;If you want my stuff then be sure to go to the &lt;code&gt;user/nic&lt;/code&gt; branch on my fork&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;You can see the ansible stuff for traefik &lt;a href=&#34;https://github.com/davestephens/ansible-nas/tree/master/roles/traefik&#34;&gt;here&lt;/a&gt;&lt;/p&gt;&#xA;&lt;h1 id=&#34;config&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Config&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;I use a &lt;code&gt;traefik.toml&lt;/code&gt; as the main config and it looks something like this.&#xA;With ansible a lot of this is done through template variables but this is the general idea.&#xA;This config tells traefik what ports to listen and forward on, and gives the names to be referenced by docker labels (down below).&lt;/p&gt;&#xA;&lt;p&gt;Traefik also has a handy web ui that with this config you can find on port &lt;code&gt;8080&lt;/code&gt;.&#xA;There is a &lt;code&gt;providers&lt;/code&gt; section - which is one of the biggest selling points of traefik for me.&#xA;I have a docker provider configured  and a static file.&lt;/p&gt;&#xA;&lt;p&gt;The docker provider lets traefik auto-discover new services that I deploy and automatically handle the routing!&#xA;The static file lets me easily add non-dockerized service routing, or routing to dockerized services on another host (I think traefik has an easier way to do this automatically but I don&amp;rsquo;t do it often enough to need that kind of automation).&#xA;Then at the bottom is the SSL cert stuff.&#xA;Using Let&amp;rsquo;s Encrypt is pretty easy and I use Cloudflare as my DNS provider&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;entryPoints&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;entryPoints&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;web&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;address&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;:80&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;entryPoints&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;web&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;http&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;redirections&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;entryPoint&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;websecure&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;entryPoints&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;websecure&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;address&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;:443&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;entryPoints&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;websecure&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;http&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;tls&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;certResolver&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;letsencrypt&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;entryPoints&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;websecure&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;http&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;tls&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;domains&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;main&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;example.com&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;sans&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;*.example.com&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;entryPoints&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;traefik&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;address&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;:8080&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;providers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;providersThrottleDuration&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;1s&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;providers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;docker&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;exposedbydefault&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;providers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;filename&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/etc/traefik/config.yml&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;api&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;insecure&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;dashboard&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;level&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;INFO&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ping&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;terminatingStatusCode&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;certificatesResolvers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;certificatesResolvers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;letsencrypt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;certificatesResolvers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;letsencrypt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;acme&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;email&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;my_email@example.com&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;storage&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/letsencrypt/acme.json&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;caserver&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://acme-staging-v02.api.letsencrypt.org/directory&amp;#34;&lt;/span&gt;  &lt;span class=&#34;c&#34;&gt;# le staging, not prod&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;certificatesResolvers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;letsencrypt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;acme&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;dnsChallenge&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;provider&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;cloudflare&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;providers-file&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Providers.file&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;To my knowledge there isn&amp;rsquo;t much to configure on the docker provider side of things until you deploy a service.&#xA;But the provider config file should get a little screen time here.&lt;/p&gt;&#xA;&lt;p&gt;The file defines a traefik http router for each service you define, in this case just &lt;code&gt;pihole&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Here I am adding my pihole instance which is not run inside docker but is inside a VM on another host.&#xA;I want the &lt;code&gt;entryPoints&lt;/code&gt; to be set to &lt;code&gt;websecure&lt;/code&gt; which is configured above in the http redirects.&#xA;I want some middlewares, &lt;code&gt;addprefix-pihole&lt;/code&gt; and &lt;code&gt;default-headers&lt;/code&gt;, which I&amp;rsquo;ll explain below.&#xA;I set letsencrypt as the cert certResolver.&#xA;Finally I name the service &lt;code&gt;pihole&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Then in the &lt;code&gt;services&lt;/code&gt; section I configure where pihole is located by just giving the internal IP for traefik to route to.&#xA;Finally I define my middlewares.&#xA;To get to the pihole homepage you need to use the route &lt;code&gt;/admin&lt;/code&gt; so I want that added automatically when I go to &lt;code&gt;pihole.example.com&lt;/code&gt; so I come to &lt;code&gt;pihole.example.com/admin&lt;/code&gt;.&#xA;And I wanted to restrict access to just my internal network and my wireguard network - this is done with the &lt;code&gt;default-whitelist&lt;/code&gt;.&#xA;The last thing is to configure a chain of middlewares that I called &lt;code&gt;secured&lt;/code&gt; which is just easier for the docker labels later on.&lt;/p&gt;&#xA;&lt;p&gt;With this config in play though, traefik will know about the route &lt;code&gt;pihole.example.com&lt;/code&gt; and handle the ip whitelisting and load balancing for me.&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;http&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;#region routers &lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;routers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;pihole&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;entryPoints&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;websecure&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;rule&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Host(`pihole.example.com`)&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;middlewares&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# - default-headers&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;addprefix-pihole&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;default-whitelist&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;tls&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;certResolver&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;letsencrypt&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;service&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;pihole&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;#region services&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;services&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;pihole&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;loadBalancer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;servers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;          &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;http://192.168.1.3:80&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;passHostHeader&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;#endregion&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;middlewares&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;addprefix-pihole&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;addPrefix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;prefix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/admin&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;https-redirect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;redirectScheme&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;scheme&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;https&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;default-headers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;headers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;frameDeny&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;sslRedirect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;browserXssFilter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;contentTypeNosniff&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;forceSTSHeader&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;stsIncludeSubdomains&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;stsPreload&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;stsSeconds&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;15552000&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;customFrameOptionsValue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;SAMEORIGIN&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;default-whitelist&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;ipWhiteList&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;sourceRange&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;10.6.0.0/24&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# wg&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;192.168.1.0/24&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# lan&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;172.17.0.0/16&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# docker&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;secured&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;chain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;middlewares&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;default-whitelist&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;default-headers&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;docker-labels&#34;&gt;&lt;span class=&#34;heading-wear-glyph&#34;&gt;Docker labels&lt;/span&gt;&lt;/h1&gt;&#xA;&lt;p&gt;Now the real magic is with Docker.&#xA;Here is an example docker-compose file for spinning up a &lt;a href=&#34;https://jellyfin.org/&#34;&gt;jellyfin&lt;/a&gt; server that you want to expose to the world, or at least access at home with &lt;code&gt;jellyfin.example.com&lt;/code&gt; instead of &lt;code&gt;http://192.168.1.N:8096&lt;/code&gt;&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;I left some of the ansible variable stuff in here, but the main part to be concerned with is the &lt;code&gt;labels&lt;/code&gt; section&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;We define just a few labels to throw onto this docker container which let&amp;rsquo;s traefik discover it automatically and apply any settings necessary (like my &lt;code&gt;ipWhiteList&lt;/code&gt;).&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;traefik.enable&lt;/code&gt; is either True or False.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;traefik.http.router.jellyfin.rule&lt;/code&gt; defines an http router called jellyfin and sets the url to &lt;code&gt;jellyfin.example.com&lt;/code&gt; (if example.com was my &lt;code&gt;ansible_nas_domain&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;traefik.http.routers.jellyfin.tls.certresolver&lt;/code&gt; is set to letsencrypt since I use LE for my wildcard certs.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;traefik.http.routers.jellyfin.tls.domains[0].main&lt;/code&gt; will just be &lt;code&gt;example.com&lt;/code&gt; -&amp;gt; and this should remind you of the toml file above&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;traefik.http.routers.jellyfin.tls.domains[0].sans&lt;/code&gt; is set to &lt;code&gt;*.example.com&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;traefik.http.services.jellyfin.loadbalancer.server.port&lt;/code&gt; is set to jellyfin&amp;rsquo;s default http port of 8096, which tells traefik which port to point to for this service.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;jellyfin&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;linuxserver/jellyfin&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;volumes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;{{ jellyfin_config_directory }}:/config:rw&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;{{ jellyfin_movies_directory }}:/movies:{{ jellyfin_movies_permissions }}&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;{{ jellyfin_music_directory }}:/music:{{ jellyfin_music_permissions }}&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;{{ jellyfin_photos_directory }}:/photos:{{ jellyfin_photos_permissions }}&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;{{ jellyfin_tv_directory }}:/tv:{{ jellyfin_tv_permissions }}&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;{{ jellyfin_books_directory }}:/books:{{ jellyfin_books_permissions }}&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;{{ jellyfin_audiobooks_directory }}:/audiobooks:{{ jellyfin_audiobooks_permissions }}&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;ports&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;{{ jellyfin_port_http }}:8096&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;{{ jellyfin_port_https }}:8920&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;env&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;TZ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;{{ ansible_nas_timezone }}&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;PUID&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;{{ jellyfin_user_id }}&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;PGID&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;{{ jellyfin_group_id }}&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;restart_policy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;unless-stopped&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;memory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;1g&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;labels&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;traefik.enable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;{{ jellyfin_available_externally }}&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;traefik.http.routers.jellyfin.rule&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Host(`jellyfin.{{ ansible_nas_domain }}`)&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;traefik.http.routers.jellyfin.tls.certresolver&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;letsencrypt&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;traefik.http.routers.jellyfin.tls.domains[0].main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;{{ ansible_nas_domain }}&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;traefik.http.routers.jellyfin.tls.domains[0].sans&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;*.{{ ansible_nas_domain }}&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;traefik.http.services.jellyfin.loadbalancer.server.port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;8096&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And just like that traefik will automagically find your jellyfin container and route &lt;code&gt;jellyfin.example.com&lt;/code&gt; to it!&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Pandas-Select-Dtypes</title>
    <id>https://pype.dev/pandas-select-dtypes/</id>
    <updated>2022-03-05T00:00:00Z</updated>
    <published>2022-03-05T00:00:00Z</published>
    <link href="https://pype.dev/pandas-select-dtypes/" rel="alternate" type="text/html"></link>
    <summary type="text">On my team we often have to change data types of columns in a for a variety of reasons. The main one is it tends to be an artifact of EDA whereby a file is...</summary>
    <content type="html">&lt;p&gt;On my team we often have to change data types of columns in a &lt;code&gt;pandas.DataFrame&lt;/code&gt; for a variety of reasons.&#xA;The main one is it tends to be an artifact of EDA whereby a file is read in via &lt;code&gt;pandas&lt;/code&gt; but the data types are somewhat wonky (ie. dates show up as strings, or a column that &lt;em&gt;should&lt;/em&gt; be a integer comes in as float, etc.).&#xA;The best solution I think is to leverage the &lt;code&gt;dtypes&lt;/code&gt; keyword argument in which &lt;code&gt;pd.read_X&lt;/code&gt; method is used.&#xA;However there is another way which is to coerce the data types at runtime instead of loadtime.&lt;/p&gt;&#xA;&lt;p&gt;A handy way to do this is by using &lt;code&gt;pandas.DataFrame.select_dtypes&lt;/code&gt;&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;Here is an example of finding columns read in as &lt;code&gt;datetime64&lt;/code&gt; and the developer would prefer to use pandas datetimes.&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read_csv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;./file-with-confusing-dtypes.csv&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;columns&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dtype&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;datetime64&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;to_datetime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here is the difference in code flow between &lt;code&gt;select_dtypes&lt;/code&gt; and manually finding the &lt;code&gt;datetype64&lt;/code&gt; columns:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read_csv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;./file-with-confusing-dtypes.csv&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;select_dtypes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;datetime64&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;to_datetime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The difference isn&amp;rsquo;t huge but it&amp;rsquo;s the little steps in leveling up that turn script-kitty scripts into clean looking functions.&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Tiddly-Wiki</title>
    <id>https://pype.dev/tiddly-wiki/</id>
    <updated>2022-03-05T00:00:00Z</updated>
    <published>2022-03-05T00:00:00Z</published>
    <link href="https://pype.dev/tiddly-wiki/" rel="alternate" type="text/html"></link>
    <summary type="text">Tiddly Wiki is a great note taking utility for organizing non-linear notes. I used it to replace my OneNote workflow and my only complaint is I don&#39;t have an...</summary>
    <content type="html">&lt;p&gt;&lt;a href=&#34;https://tiddlywiki.com/&#34;&gt;Tiddly Wiki&lt;/a&gt; is a great note taking utility for organizing non-linear notes.&#xA;I used it to replace my OneNote workflow and my only complaint is I don&amp;rsquo;t have an easy way to access and edit my tiddlers (posts) if I&amp;rsquo;m not at home.&lt;/p&gt;&#xA;&lt;p&gt;The tiddlywiki is just an &lt;code&gt;html&lt;/code&gt; file with a ton of stuff above my head baked in.&#xA;I have a barebones repo with some notes and a nice starter tiddly wiki init on &lt;a href=&#34;https://github.com/nicpayne713/tiddlywiki-tutorial&#34;&gt;my github&lt;/a&gt;.&#xA;Usage is pretty basic&amp;hellip; Just grab the &lt;code&gt;notebook/template.htlm&lt;/code&gt; and save it to anywhere convenient on your computer.&#xA;I put mine on my NAS to have the security of backups since I don&amp;rsquo;t keep my tidldlywiki in a git repo (I don&amp;rsquo;t really want to look at the diff).&lt;/p&gt;&#xA;&lt;p&gt;Taking notes in the tidlywiki is nice because it supports a format similar to Markdown although it is specific to tidlywiki.&#xA;Tiddlers (each post in the wiki) can be tagged and linked together and it&amp;rsquo;s really easy to send notes to someone by just exporting an html file and emailing it since it&amp;rsquo;ll open up by default in a broswer with all the nice formatting already apart of it.&#xA;I was using it primarily for taking notes for a small group I lead and sending those notes each week.&#xA;The group benefited from nicely formatted notes and I benefited from a centralized place to keep them all that Microsoft didn&amp;rsquo;t own!&lt;/p&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s an example of the body of a tiddler with some tiddlywiki specific formatting:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;! Static IPs on Linux&#xA;&#xA;//Ubuntu 20//&#xA;&#xA;Setting static IP on Ubuntu 20.04&#xA;&#xA;# Navigate to /etc/netplan&#xA;# Open the yaml file (the name seems to be kind of random but it seems to starts with 00 or 05)&#xA;# Change the file as below with your desired settings&#xA;# Run `sudo netplan apply` to have changes reflected&#xA;&#xA;    ```yaml&#xA;    network:&#xA;      version: 2&#xA;      ethernets:&#xA;        enp0s4:&#xA;          addresses: [192.168.1.{Static IP}/24]&#xA;          gateway4: 192.168.1.1&#xA;          nameservers:&#xA;            addresses: [8.8.4.4, 8.8.8.8]&#xA;    ```&#xA;&#xA;&#xA;&#xA;&amp;lt;img src=&amp;quot;https://cdn.statically.io/gh/pypeaday/images.pype.dev/main/tiddlywiki-example.png&amp;quot; alt=&amp;quot;tiddlywiki&amp;quot; title=&amp;quot;A TiddlyWiki Example&amp;quot; /&amp;gt;&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The &lt;code&gt;#&lt;/code&gt; create a numbered list, &lt;code&gt;//&lt;/code&gt; creates an italicized heading, and &lt;code&gt;!&lt;/code&gt; creates headings similar to Markdown&amp;rsquo;s &lt;code&gt;#&lt;/code&gt;. The differences aren&amp;rsquo;t too bad to keep in mind and what renders out is totally depenent on the tidlywiki itself.&#xA;My template has a nice nord feel to it, feel free to download from my github and try it out!&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;I have moved away from my tiddlywiki workflow in favor of sites like this since I can git commit markdown files and build with &lt;a href=&#34;https://markata.dev/&#34;&gt;markata&lt;/a&gt; pretty easily (credit &lt;a href=&#34;www.waylonwalker.com&#34;&gt;waylon walker&lt;/a&gt;)&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;I still use tiddlywiki for tracking some todo items and questions &amp;mdash; I may have another solution in the future&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Vim-Auto-Space</title>
    <id>https://pype.dev/vim-auto-space/</id>
    <updated>2022-03-04T00:00:00Z</updated>
    <published>2022-03-04T00:00:00Z</published>
    <link href="https://pype.dev/vim-auto-space/" rel="alternate" type="text/html"></link>
    <summary type="text">I ran into an issue where I had some copy-pasta markdown tables in a docstring but the generator I used to make the table gave me tabs instead of spaces in...</summary>
    <content type="html">&lt;p&gt;I ran into an issue where I had some copy-pasta markdown tables in a docstring but the generator I used to make the table gave me tabs instead of spaces in odd places which caused &lt;code&gt;black&lt;/code&gt; to throw a fit.&#xA;Instead of manually changing all tabs to spaes, or trying some goofy &lt;code&gt;:%s/&amp;lt;magic tab character&amp;gt;/&amp;lt;%20 maybe?&amp;gt;/g&lt;/code&gt; I learned that Vim has my back&amp;hellip;&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;:retab&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Stow</title>
    <id>https://pype.dev/stow/</id>
    <updated>2022-03-04T00:00:00Z</updated>
    <published>2022-03-04T00:00:00Z</published>
    <link href="https://pype.dev/stow/" rel="alternate" type="text/html"></link>
    <summary type="text">Stow is a great tool for managing dotfiles. My usage looks like cloning my dotfiles to my home directory, setting some environment variables via a script,...</summary>
    <content type="html">&lt;p&gt;Stow is a great tool for managing dotfiles. My usage looks like cloning my dotfiles to my home directory, setting some environment variables via a script, then stowing relevant packages and boom my config is good to go&amp;hellip;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; ~&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git clone &amp;lt;my dotfiles repo&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; dotfiles&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# env variable stuff ignored here&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;stow zsh  &lt;span class=&#34;c1&#34;&gt;# This will symlink my .zshrc file which is in ~/dotfiles/zsh to ~/.zshrc&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;By default stow will stow packages up one directory from the root directory.&#xA;In this example the root directory is &lt;code&gt;~/dotfiles&lt;/code&gt; and the package is &lt;code&gt;zsh&lt;/code&gt;.&#xA;So the files in the &lt;code&gt;zsh&lt;/code&gt; package will symlinked into &lt;code&gt;~/&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;stow&lt;/code&gt; makes it easy to share dotfiles across machines, or safely experiment with config changes while always being protected by &lt;code&gt;git&lt;/code&gt; since your dotfiles are in a git repo!&#xA;&amp;hellip;They are in a git repo&amp;hellip; right?&lt;/p&gt;&#xA;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Stow-Target</title>
    <id>https://pype.dev/stow-target/</id>
    <updated>2022-03-04T00:00:00Z</updated>
    <published>2022-03-04T00:00:00Z</published>
    <link href="https://pype.dev/stow-target/" rel="alternate" type="text/html"></link>
    <summary type="text">Check out stow for a brief introduction to</summary>
    <content type="html">&lt;p&gt;Check out &lt;a href=&#34;/stow&#34;&gt;stow&lt;/a&gt; for a brief introduction to &lt;code&gt;stow&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;What if I want to stow a package somewhere else?&#xA;Boom, that&amp;rsquo;s where &lt;code&gt;-t&lt;/code&gt; comes in&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;Maybe I don&amp;rsquo;t like having my &lt;code&gt;dotfiles&lt;/code&gt; repo at &lt;code&gt;$HOME&lt;/code&gt; and instead I want it in &lt;code&gt;~/git&lt;/code&gt; or &lt;code&gt;~/personal&lt;/code&gt; just to stay organized&amp;hellip;&#xA;Well then I could have the same workflow except the &lt;code&gt;stow&lt;/code&gt; command looks like this:&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;stow zsh -t ~/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;#or&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;stow zsh -t &lt;span class=&#34;nv&#34;&gt;$HOME&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
  <entry>
    <title>Git ammend to a commit</title>
    <id>https://pype.dev/git-ammend-no-edit/</id>
    <updated>2022-03-04T00:00:00Z</updated>
    <published>2022-03-04T00:00:00Z</published>
    <link href="https://pype.dev/git-ammend-no-edit/" rel="alternate" type="text/html"></link>
    <summary type="text">After carefully staging only lines related to a specific change and comitting I suddenly realized I missed one... darn, what do I do?</summary>
    <content type="html">&lt;p&gt;After carefully staging only lines related to a specific change and comitting I suddenly realized I missed one&amp;hellip; darn, what do I do?&lt;/p&gt;&#xA;&lt;p&gt;Old me would have soft reset my branch to the previous commit and redone all my careful staging&amp;hellip; what a PIA&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;New me (credit: ThePrimeagen)&amp;hellip;&lt;/p&gt;&#xA;&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# stage other changes I missed&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git commit --amend --no-edit&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
    <author>
      <name>Nic Payne</name>
      <uri>https://pype.dev</uri>
    </author>
  </entry>
</feed>