URI:
       nextjs_daan.fyi.rss.xml - sfeed_tests - sfeed tests and RSS and Atom files
  HTML git clone git://git.codemadness.org/sfeed_tests
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       nextjs_daan.fyi.rss.xml (83182B)
       ---
            1 <?xml version="1.0" encoding="utf-8"?>
            2 <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
            3     <channel>
            4         <title>Daan Debie</title>
            5         <link>https://www.daan.fyi/</link>
            6         <description>This is a feed of all posts on the website of Daan Debie</description>
            7         <lastBuildDate>Mon, 29 Nov 2021 20:04:24 GMT</lastBuildDate>
            8         <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
            9         <generator>NextJS + feed package</generator>
           10         <language>en</language>
           11         <image>
           12             <title>Daan Debie</title>
           13             <url>https://www.daan.fyi/images/banner.png</url>
           14             <link>https://www.daan.fyi/</link>
           15         </image>
           16         <copyright>Copyright 2021 - Daan Debie</copyright>
           17         <item>
           18             <title><![CDATA[Customzing Pyenv Behavior with Hooks]]></title>
           19             <link>https://www.daan.fyi/writings/pyenv-hooks</link>
           20             <guid>https://www.daan.fyi/writings/pyenv-hooks</guid>
           21             <pubDate>Sun, 28 Nov 2021 00:00:00 GMT</pubDate>
           22             <description><![CDATA[You can customize the behavior of pyenv or its plugins - like pyenv virtualenv - by using hooks. These are simple (bash) scripts that are run at specific points when pyenv commands are run.]]></description>
           23             <content:encoded><![CDATA[<p class="chakra-text css-rszk63">I use <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://github.com/pyenv/pyenv">pyenv</a> to manage different Python versions on my laptop. It
           24 also comes with an <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://github.com/pyenv/pyenv-virtualenv">official plugin</a> that lets you manage
           25 <em>virtualenvs</em> through pyenv, which I find very convenient. Basically, virtualenvs are treated as
           26 just different Python versions by pyenv.</p> <p class="chakra-text css-rszk63">One thing that bothered me is that, whenever I create a new virtualenv and use <code class="chakra-code css-4m8w8z">pip</code> in it, I am
           27 inevitably greeted by a message telling me <code class="chakra-code css-4m8w8z">pip</code> is out-of-date:</p><pre><code>WARNING: You are using pip version 21.2.3; however, version 21.3.1 is available.
           28 You should consider upgrading via the '~/.pyenv/versions/3.10.0/envs/test/bin/python3.10 -m pip install --upgrade pip' command.
           29 </code></pre> <p class="chakra-text css-rszk63">So I end up always having to upgrade pip after creating a new virtualenv. Wouldn’t it be nice if
           30 this could be automated?</p> <p class="chakra-text css-rszk63">Turns out, we actually <em>can</em> by leveraging <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://github.com/pyenv/pyenv/wiki/Authoring-plugins#pyenv-hooks"><em>pyenv hooks</em></a>.</p> <h2 class="chakra-heading css-13bekiy" id="pyenv-hooks"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/pyenv-hooks#pyenv-hooks"><span class="icon icon-link"></span></a>Pyenv Hooks</h2> <p class="chakra-text css-rszk63">pyenv hooks are scripts that are executed by pyenv whenever certain commands are run. These can be
           31 regular pyenv commands like <code class="chakra-code css-4m8w8z">pyenv install</code> or <code class="chakra-code css-4m8w8z">pyenv rehash</code> for example. But what is not
           32 apparent from the pyenv documentation, is that you can also create hooks for plugins, like
           33 <code class="chakra-code css-4m8w8z">pyenv virtualenv</code>.</p> <p class="chakra-text css-rszk63">You can create a hook by creating a script at the following location:</p><pre class="language-bash"><code class="language-bash"><span class="token variable">$PYENV_ROOT</span>/pyenv.d/<span class="token operator"><</span>hook-name<span class="token operator">></span>/<span class="token operator"><</span>whatever<span class="token operator">></span>.bash
           34 </code></pre> <p class="chakra-text css-rszk63"> <code class="chakra-code css-4m8w8z">hook-name</code> here can be any of: <code class="chakra-code css-4m8w8z">exec</code>, <code class="chakra-code css-4m8w8z">rehash</code>, <code class="chakra-code css-4m8w8z">which</code>, <code class="chakra-code css-4m8w8z">install</code> — which are all regular pyenv
           35 commands — but it can also be a plugin command, like <code class="chakra-code css-4m8w8z">virtualenv</code>. The filename of the script doesn’t
           36 matter, and neither does the extension. I use <code class="chakra-code css-4m8w8z">.bash</code> here to make it explicit that this is a bash
           37 script, but pyenv hooks can be written in any language.</p> <p class="chakra-text css-rszk63">To create a hook that upgrades <code class="chakra-code css-4m8w8z">pip</code> and some other default packages, you can create a new script
           38 as follows:</p><pre class="language-bash"><code class="language-bash"><span class="token function">mkdir</span> -p <span class="token variable">$PYENV_ROOT</span>/pyenv.d/virtualenv/
           39 <span class="token variable">$EDITOR</span> <span class="token variable">$PYENV_ROOT</span>/pyenv.d/virtualenv/after.bash
           40 </code></pre> <p class="chakra-text css-rszk63">Where <code class="chakra-code css-4m8w8z">$EDITOR</code> is your favorite editor (like <code class="chakra-code css-4m8w8z">vim</code>, <strong>RIGHT?!</strong>)</p> <p class="chakra-text css-rszk63">Then add the following contents:</p><pre class="language-bash"><code class="language-bash">after_virtualenv <span class="token string">'PYENV_VERSION="<span class="token variable">$VIRTUALENV_NAME</span>" pyenv-exec pip install --upgrade pip setuptools wheel'</span>
           41 </code></pre> <p class="chakra-text css-rszk63"> <code class="chakra-code css-4m8w8z">after_virtualenv</code> is the command that tells pyenv <em>when</em> to execute the following command. In this
           42 case its defined by the <code class="chakra-code css-4m8w8z">pyenv virtualenv</code> plugin. First we set the pyenv version to the name
           43 of the virtualenv we just created. This is set by pyenv virtualenv as <code class="chakra-code css-4m8w8z">$VIRTUALENV_NAME</code>. Then we
           44 install/upgrade <code class="chakra-code css-4m8w8z">pip</code> itself and <code class="chakra-code css-4m8w8z">setuptools</code> and <code class="chakra-code css-4m8w8z">wheel</code>.</p> <p class="chakra-text css-rszk63">That is all there is to it! Now any time you create a new virtualenv using <code class="chakra-code css-4m8w8z">pyenv virtualenv</code>, the
           45 aforementioned packages will be automatically upgraded after the virtualenv was created.</p><span></span>]]></content:encoded>
           46         </item>
           47         <item>
           48             <title><![CDATA[Static Duck Typing in Python with Protocols]]></title>
           49             <link>https://www.daan.fyi/writings/python-protocols</link>
           50             <guid>https://www.daan.fyi/writings/python-protocols</guid>
           51             <pubDate>Fri, 19 Nov 2021 00:00:00 GMT</pubDate>
           52             <description><![CDATA[Duck typing is considered to be one of Python's strengths. If you want to have the benefits of duck typing but also want your types statically checked, Protocols offer an excellent solution.]]></description>
           53             <content:encoded><![CDATA[<p class="chakra-text css-rszk63">At <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://source.ag/">Source</a>, we write most of our code in Python. It’s a language that both our
           54 Software Engineers and Data Scientists are equally at home in. It’s easy to be productive in Python,
           55 in part due to its dynamic nature. Not having to think too much about the types of your variables
           56 and functions, can make it easier to experiment, especially if you’re not entirely clear yet
           57 on how you’re going to solve a particular problem.</p> <p class="chakra-text css-rszk63">When moving our code to production however, we want to have more guarantees about the behaviour of
           58 our code. Writing (unit) tests is one way to get those guarantees, but we also make heavy use of <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://www.python.org/dev/peps/pep-0484/">type hints</a> to give us more confidence in our code.
           59 Type hints can also provide a productivity boost, because not only humans can reason better about
           60 type hinted code, your editor can as well!</p> <p class="chakra-text css-rszk63">Sometimes though, using type hints everywhere can feel like you’re losing out on a lot of the magic
           61 and speed that a dynamic type system brings you. One particular trait of dynamic typing that is
           62 pretty idiomatic in Python, is <strong>duck typing</strong>.</p> <h2 class="chakra-heading css-13bekiy" id="duck-typing"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/python-protocols#duck-typing"><span class="icon icon-link"></span></a>Duck Typing</h2> <p class="chakra-text css-rszk63"> <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://en.wikipedia.org/wiki/Duck_typing">Duck typing</a> is a philosophy in programming where you
           63 care more about the behaviour and properties of an object than its stated type to determine if that
           64 object is useful in a certain situation. Duck typing is inspired by the <em>duck test</em>:</p> <blockquote class="css-p56y4k"> <p class="chakra-text css-rszk63">If it walks like a duck and it quacks like a duck, then it must be a duck</p></blockquote> <p class="chakra-text css-rszk63">In practice this means that when you write a function that receives a certain input, you care only
           65 about the behaviour and/or attributes of that input, not the explicit <em>type</em> of that input.</p> <p class="chakra-text css-rszk63">One interesting question that arises is: if you don’t want to be strict about the type of the
           66 parameters a function receives, are there still any <em>static type guarantees</em> to be had?</p> <p class="chakra-text css-rszk63">And the other way around is interesting as well: if you have a function with statically typed
           67 inputs, can you <em>loosen up</em> those parameters to make the function more universally useful, the way
           68 duck typing does?</p> <p class="chakra-text css-rszk63">As it turns out, Python provides a neat way to have our cake and eat it too!</p> <h2 class="chakra-heading css-13bekiy" id="protocols-to-the-rescue"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/python-protocols#protocols-to-the-rescue"><span class="icon icon-link"></span></a>Protocols to the Rescue</h2> <p class="chakra-text css-rszk63">When reviewing some code recently, I came across a function that looked roughly like this:</p><pre class="language-python"><code class="language-python"><span class="token keyword">def</span> <span class="token function">calculate_windowed_avg</span><span class="token punctuation">(</span>
           69         measurements<span class="token punctuation">:</span> Union<span class="token punctuation">[</span>List<span class="token punctuation">[</span>TemperatureMeasurement<span class="token punctuation">]</span><span class="token punctuation">,</span> List<span class="token punctuation">[</span>HumidityMeasurement<span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
           70         window_size<span class="token punctuation">:</span> timedelta<span class="token punctuation">,</span>
           71         field_name<span class="token punctuation">:</span> <span class="token builtin">str</span>
           72     <span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> Dict<span class="token punctuation">[</span>datetime<span class="token punctuation">,</span> <span class="token builtin">float</span><span class="token punctuation">]</span><span class="token punctuation">:</span>
           73     window_upper_bound <span class="token operator">=</span> measurements<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>timestamp <span class="token operator">+</span> window_size
           74     current_window <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
           75     window_averages <span class="token operator">=</span> OrderedDict<span class="token punctuation">(</span><span class="token punctuation">)</span>
           76     <span class="token keyword">for</span> m <span class="token keyword">in</span> measurements<span class="token punctuation">:</span>
           77         <span class="token comment"># various calculations happen here</span>
           78         <span class="token comment"># based on the timestamp of each measurement</span>
           79         <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
           80     <span class="token keyword">return</span> window_averages
           81 </code></pre> <p class="chakra-text css-rszk63">The goal of this function is to calculate the average of a certain field (identified by <code class="chakra-code css-4m8w8z">field_name</code>) in a rolling window. At the time of writing this function, we were using it for
           82 <code class="chakra-code css-4m8w8z">TemperatureMeasurement</code> and <code class="chakra-code css-4m8w8z">HumidityMeasurement</code>, but it is very likely we’ll want to use it for
           83 different types of measurements in the future.</p> <p class="chakra-text css-rszk63">If we look closely at how the function uses the input, it turns out that the only thing we want to
           84 be guaranteed of, is that the items we pass into the function have a <code class="chakra-code css-4m8w8z">timestamp</code> field. So instead
           85 of specifying each different type that has adheres to this contract, we’d like to tell the type
           86 checker that we only care about having a <code class="chakra-code css-4m8w8z">timestamp</code> field to work with.</p> <p class="chakra-text css-rszk63"> <code class="chakra-code css-4m8w8z">Protocol</code> from the <code class="chakra-code css-4m8w8z">typing</code> module lets us do that. Just like with duck typing, <strong>Protocols</strong> let
           87 you specify the behaviour or attributes you expect, without caring about the type. Here is what
           88 that looks like:</p><pre class="language-python"><code class="language-python{4,5,8}"><span class="token keyword">from</span> typing <span class="token keyword">import</span> Protocol<span class="token punctuation">,</span> List<span class="token punctuation">,</span> Dict
           89 <span class="token keyword">from</span> datetime <span class="token keyword">import</span> datetime
           90 
           91 <div class="mdx-marker"><span class="token keyword">class</span> <span class="token class-name">MeasurementLike</span><span class="token punctuation">(</span>Protocol<span class="token punctuation">)</span><span class="token punctuation">:</span>
           92 </div><div class="mdx-marker">    timestamp<span class="token punctuation">:</span> datetime
           93 </div>
           94 <span class="token keyword">def</span> <span class="token function">calculate_windowed_avg</span><span class="token punctuation">(</span>
           95 <div class="mdx-marker">        measurements<span class="token punctuation">:</span> List<span class="token punctuation">[</span>MeasurementLike<span class="token punctuation">]</span><span class="token punctuation">,</span>
           96 </div>        window_size<span class="token punctuation">:</span> timedelta<span class="token punctuation">,</span>
           97         field_name<span class="token punctuation">:</span> <span class="token builtin">str</span>
           98     <span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> Dict<span class="token punctuation">[</span>datetime<span class="token punctuation">,</span> <span class="token builtin">float</span><span class="token punctuation">]</span><span class="token punctuation">:</span>
           99     window_upper_bound <span class="token operator">=</span> measurements<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>timestamp <span class="token operator">+</span> window_size
          100     <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
          101 </code></pre> <p class="chakra-text css-rszk63">Now the type checker doesn’t know <em>exactly</em> what the type is of whatever is provided as <code class="chakra-code css-4m8w8z">measurements</code> but it <em>does</em> know what those items have a <code class="chakra-code css-4m8w8z">timestamp</code> field because they adhere to
          102 the <code class="chakra-code css-4m8w8z">MeasurementLike</code> Protocol.</p> <p class="chakra-text css-rszk63">In a sense, a Protocol acts like one side of an <em>Interface</em> as we know it from Java or Typescript.
          103 Instead of having to specify the behaviour and properties both on a <em>type</em> and on the functions
          104 that use it, we only have to specify it on a function, without caring about the types of the objects
          105 that are provided to the function.</p> <h2 class="chakra-heading css-13bekiy" id="protocol-and-generics"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/python-protocols#protocol-and-generics"><span class="icon icon-link"></span></a>Protocol and Generics</h2> <p class="chakra-text css-rszk63">You can also use Protocols together with <code class="chakra-code css-4m8w8z">TypeVar</code> for even more generic functions that are still
          106 type checked to some extend. One use-case that comes to mind, is when you don’t care about the
          107 input type to a function, as long as it follows a protocol, but you also want to guarantee that
          108 the <em>output</em> of the function is of the same type as the <em>input</em>, no matter what the exact type is.</p> <p class="chakra-text css-rszk63">This works as follows:</p><pre class="language-python"><code class="language-python"><span class="token keyword">from</span> typing <span class="token keyword">import</span> Protocol<span class="token punctuation">,</span> TypeVar
          109 <span class="token keyword">from</span> datetime <span class="token keyword">import</span> datetime
          110 
          111 <span class="token keyword">class</span> <span class="token class-name">MeasurementLike</span><span class="token punctuation">(</span>Protocol<span class="token punctuation">)</span><span class="token punctuation">:</span>
          112     timestamp<span class="token punctuation">:</span> datetime
          113 
          114 M <span class="token operator">=</span> TypeVar<span class="token punctuation">(</span><span class="token string">'M'</span><span class="token punctuation">,</span> bound<span class="token operator">=</span>MeasurementLike<span class="token punctuation">)</span>
          115 
          116 <span class="token keyword">def</span> <span class="token function">measurement_as_timezone</span><span class="token punctuation">(</span>measurement<span class="token punctuation">:</span> M<span class="token punctuation">,</span> tz<span class="token punctuation">:</span> tzinfo<span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> M<span class="token punctuation">:</span>
          117     measurement<span class="token punctuation">.</span>timestamp <span class="token operator">=</span> measurement<span class="token punctuation">.</span>timestamp<span class="token punctuation">.</span>astimezone<span class="token punctuation">(</span>tz<span class="token punctuation">)</span>
          118     <span class="token keyword">return</span> measurement
          119 </code></pre> <p class="chakra-text css-rszk63">Here we create a function that takes any object that has a <code class="chakra-code css-4m8w8z">timestamp</code> field and guarantees that
          120 the output will be of the same type as the input.</p> <h2 class="chakra-heading css-13bekiy" id="conclusion"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/python-protocols#conclusion"><span class="icon icon-link"></span></a>Conclusion</h2> <p class="chakra-text css-rszk63">Protocols in Python provide a nice way to use duck typing while still having some static type
          121 guarantees. You can define contracts for your functions without caring too much about the actual
          122 types of your inputs.</p> <hr aria-orientation="horizontal" class="chakra-divider css-9153ub"/> <p class="chakra-text css-rszk63"><em>Update on 2021–11–23: There was a wrong type annotation in this article, as <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://news.ycombinator.com/item?id=29315363">pointed out by
          123 <strong>ragebol</strong> on Hacker News</a>, which is now fixed</em></p><span></span>]]></content:encoded>
          124         </item>
          125         <item>
          126             <title><![CDATA[How to Add an Rss Feed to a Nextjs Blog]]></title>
          127             <link>https://www.daan.fyi/writings/rss</link>
          128             <guid>https://www.daan.fyi/writings/rss</guid>
          129             <pubDate>Tue, 05 Oct 2021 00:00:00 GMT</pubDate>
          130             <description><![CDATA[RSS is an important feature to give your content maximum exposure while also retaining control over your content. This post shows how to add syndication feeds to a statically generated NextJS site]]></description>
          131             <content:encoded><![CDATA[<p class="chakra-text css-rszk63">Today, I released a new version of my website with only one new feature: <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://en.wikipedia.org/wiki/Web_syndication">syndication</a> through RSS, Atom and JSON Feed. Even
          132 though <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://techcrunch.com/2018/04/07/rss-is-undead/">by some accounts</a>, RSS
          133 <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://mjtsai.com/blog/2019/12/26/apple-news-no-longer-supports-rss/">seems to be dead</a>,
          134 I strongly believe RSS is an important feature in the fight to keep ownership over your own content
          135 while also increasing exposure. The way I approach publishing and sharing my content, is called
          136 <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://indieweb.org/POSSE">POSSE</a>:</p> <blockquote class="css-p56y4k"> <p class="chakra-text css-rszk63"><strong>Publish (on your) Own Site, Syndicate Elsewhere</strong>.</p></blockquote> <p class="chakra-text css-rszk63">RSS is an important part of that strategy.</p> <p class="chakra-text css-rszk63">Luckily, I’m not the only one who values RSS. <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://news.ycombinator.com/item?id=20813021">There</a>
          137 <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://news.ycombinator.com/item?id=23212812">are</a> <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://news.ycombinator.com/item?id=26014344">others</a></p> <p class="chakra-text css-rszk63">In this article I want to share how I implemented syndication feeds in my <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://nextjs.org/">NextJS-powered</a> website.</p> <h2 class="chakra-heading css-13bekiy" id="options-and-requirements"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/rss#options-and-requirements"><span class="icon icon-link"></span></a>Options and Requirements</h2> <p class="chakra-text css-rszk63">I did some Googling to see how other NextJS users were generating RSS feeds, and there turned out
          138 to be many people that had solved this particular problem <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://www.google.com/search?q=rss+feed+nextjs">and wrote about it</a>
codemadness.org:70 /git/sfeed_tests/file/input/sfeed/realworld/nextjs_daan.fyi.rss.xml.gph:149: line too long