<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>fq.nz</title>
    <description>fq.nz is a blog about computer programming, GNU/Linux, AI (Artificial Intellignece), FOSS (Free Open Source Software), privacy, information security and free culture.
</description>
    <link>https://fq.nz//</link>
    <atom:link href="https://fq.nz//feed.xml" rel="self" type="application/rss+xml" />
    <pubDate>Tue, 20 Jan 2026 14:27:11 +1300</pubDate>
    <lastBuildDate>Tue, 20 Jan 2026 14:27:11 +1300</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>Python Necromancy</title>
        <description>&lt;p&gt;This year I had deal with reviewing two old projects.
Both projects had Python 2 support and Python 3 compatibility with &lt;a href=&quot;https://six.readthedocs.io/&quot;&gt;six&lt;/a&gt;.
Both had been using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setup.py&lt;/code&gt; for installation and can not be installed on any
of the modern &amp;amp; currently supported Python versions.
But I was fortunate that both projects had tests.
Here’s my action plan for Python necromancy.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;If projects are on PyPI and test PyPI, make sure that you have maintainer/
owner access to the old project. If you don’t you will have to create separate
projects on PyPI and test PyPI.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Convert old setup systems to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pyproject.toml&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;With the above step you will have to update the dependencies as well.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Drop support for any unsupported Python versions. This will make your life
easier with dealing with dependencies and not having to support Python 2 or
older versions.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;When possible drop any dependencies. Less dependencies to worry about is
always a plus.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;When possible drop any features that doesn’t require. Try to get the MVP
(Minimal Viable Product), you can always look to add any missing features later
on.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;When the package is installable, do some manual tests to see the intended
features are working as intended.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Delete any special Python 2 checks and Python 2 specific logic. Lot of
projects that have transitioned Python 3 will have checks for the Python
version.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If you are lucky to have tests, use &lt;a href=&quot;https://tox.wiki/en/4.32.0/&quot;&gt;tox&lt;/a&gt; to run tests for all
supported Python versions.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Work on fixing tests, you might have to make judgement calls about keeping
some tests or making complex tests simpler.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Add tests as a CI/CD test.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Add &lt;a href=&quot;https://docs.pypi.org/trusted-publishers/using-a-publisher/&quot;&gt;PyPI Trusted Publisher&lt;/a&gt; to your projects.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Optional steps:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Remove &lt;a href=&quot;https://six.readthedocs.io/&quot;&gt;six&lt;/a&gt; logic.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Use &lt;a href=&quot;https://black.readthedocs.io/en/stable/&quot;&gt;black&lt;/a&gt; or &lt;a href=&quot;https://docs.astral.sh/ruff/&quot;&gt;ruff&lt;/a&gt; to format code.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

</description>
        <pubDate>Tue, 30 Dec 2025 12:23:23 +1300</pubDate>
        <link>https://fq.nz//blog/2025/12/30/python-necromancy</link>
        <guid isPermaLink="true">https://fq.nz//blog/2025/12/30/python-necromancy</guid>
        
        
        <category>python</category>
        
        <category>python2</category>
        
        <category>python3</category>
        
        <category>pypi</category>
        
        <category>pyproject</category>
        
      </item>
    
      <item>
        <title>Lightning Talk - How docker best practices can haunt you. 👻</title>
        <description>&lt;p&gt;Here’s my first lightning talk from &lt;a href=&quot;https://2024.pycon.org.au/&quot;&gt;PyCon AU 2024&lt;/a&gt; that was held in
Narrm (Melbourne), Australia this year.
This was given in the DevOops (not a typo) specialized track. I also gave
&lt;a href=&quot;/blog/2024/11/30/pycon-au-2024-lightning-talk&quot;&gt;another lightning talk&lt;/a&gt; (much more prepared than this) on very
next day in the main conference.
This speech is about the unforeseen issues caused by following best practices
with docker in production deployments. This was an unprepared talk, I didn’t
practice it all and it was spur of the moment thing to submit the talk.
I didn’t have any presentation slides but since all other speakers had on I
created landing slide to fill the space, just couple of talks before mine. :)&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://2024.pycon.org.au/&quot;&gt;PyCon AU 2024&lt;/a&gt; had lightning talks threee different days (Friday
on specialized DevOops tack, Saturday and Sunday). PyCon AU was highly
educational and entreating. There were lots of &lt;a href=&quot;https://www.youtube.com/watch?v=xVjlVYFrJj4&amp;amp;list=PLs4CJRBY5F1Jn7fWZyMgogpPsu1vAZKB2&quot;&gt;interesting talks&lt;/a&gt;, I
highly recommend watching the talks and attending future PyCon AUs.&lt;/p&gt;

&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/TkaujGy3GBI?si=FxM0nWCFO0c1_ICb&amp;amp;start=1740&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;(Source:  &lt;a href=&quot;https://www.youtube.com/watch?v=TkaujGy3GBI&quot;&gt;“DevOops Lightning talks” - Evan Kohilas (Pycon AU 2024)&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Other talks from PyCon XI 2024 can be found &lt;a href=&quot;https://www.youtube.com/watch?v=xVjlVYFrJj4&amp;amp;list=PLs4CJRBY5F1Jn7fWZyMgogpPsu1vAZKB2&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
        <pubDate>Sun, 01 Dec 2024 13:46:00 +1300</pubDate>
        <link>https://fq.nz//blog/2024/12/01/pycon-au-2024-devoops-lightning-talk</link>
        <guid isPermaLink="true">https://fq.nz//blog/2024/12/01/pycon-au-2024-devoops-lightning-talk</guid>
        
        
        <category>python</category>
        
        <category>lightning</category>
        
        <category>talk</category>
        
        <category>devops</category>
        
        <category>docker</category>
        
      </item>
    
      <item>
        <title>Lightning Talk - How to create your own RFC</title>
        <description>&lt;p&gt;Here’s my lightning talk from &lt;a href=&quot;https://2024.pycon.org.au/&quot;&gt;PyCon AU 2024&lt;/a&gt; that was held in Narrm
(Melbourne), Australia this year.
The speech is about writing your an &lt;a href=&quot;https://www.ietf.org/participate/ids/&quot;&gt;Internet-Draft&lt;/a&gt; (I-D) and how &lt;a href=&quot;https://www.ietf.org/process/rfcs/&quot;&gt;RFC&lt;/a&gt;s
are generated.
This was my second lightning talk of the conference, I gave another talk a day
before in DevOops (not a typo) specialized track. I was bit more prepared for
this talk. I made the presentation and example draft in early of lighting talk
day and did some adjustments up until the last few hours.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://2024.pycon.org.au/&quot;&gt;PyCon AU 2024&lt;/a&gt; had lightning talks threee different days (Friday
on specialized DevOops tack, Saturday and Sunday). PyCon AU was highly
educational and entreating. There were lots of &lt;a href=&quot;https://www.youtube.com/watch?v=xVjlVYFrJj4&amp;amp;list=PLs4CJRBY5F1Jn7fWZyMgogpPsu1vAZKB2&quot;&gt;interesting talks&lt;/a&gt;, I
highly recommend watching the talks and attending future PyCon AUs.&lt;/p&gt;

&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/ajJ1n2o1NN0?si=jd1Nl0NxBXq8eFfu&amp;amp;start=1345&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;(Source:  &lt;a href=&quot;https://www.youtube.com/watch?v=ajJ1n2o1NN0&quot;&gt;“Lightning Talks (Saturday)” - Christopher Neugebauer (Pycon AU 2024)&lt;/a&gt;)&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/blobs/pycon_au_rfc.pdf&quot;&gt;Presentation slides&lt;/a&gt; in PDF format.&lt;/li&gt;
  &lt;li&gt;Sample I-D: &lt;a href=&quot;https://github.com/kesara/lightning-talks&quot;&gt;draft-rathnayake-lightning-talks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Other talks from PyCon XI 2024 can be found &lt;a href=&quot;https://www.youtube.com/watch?v=xVjlVYFrJj4&amp;amp;list=PLs4CJRBY5F1Jn7fWZyMgogpPsu1vAZKB2&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
        <pubDate>Sat, 30 Nov 2024 13:36:00 +1300</pubDate>
        <link>https://fq.nz//blog/2024/11/30/pycon-au-2024-lightning-talk</link>
        <guid isPermaLink="true">https://fq.nz//blog/2024/11/30/pycon-au-2024-lightning-talk</guid>
        
        
        <category>python</category>
        
        <category>lightning</category>
        
        <category>talk</category>
        
        <category>ietf</category>
        
        <category>rfc</category>
        
        <category>internet-drafts</category>
        
        <category>xml2rfc</category>
        
      </item>
    
      <item>
        <title>Time travel with Python</title>
        <description>&lt;p&gt;Testing time is crucial in software development, especially for applications
that rely on time-based functionality. Time-based tests ensure that features
like scheduling, expiration, and logging work correctly across different time
zones and daylight-saving changes.&lt;/p&gt;

&lt;p&gt;To test that your time-based logic works correctly, you need to do time travel.
This blog post lists a few ways to test time-based logic with Python in other
words, &lt;strong&gt;How to time travel with Python&lt;/strong&gt;. After all, Python comes with
&lt;strong&gt;antigravity&lt;/strong&gt;. Just &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;import antigravity&lt;/code&gt;. :)
So time travel should be a breeze.&lt;/p&gt;

&lt;p&gt;For testing, let’s say we have a file called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new_year.py&lt;/code&gt; with the following
code. It is a simple function that returns whether the current day is the
new year or not.&lt;/p&gt;

&lt;h5 id=&quot;source-code-for-new_yearpy&quot;&gt;Source code for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new_year.py&lt;/code&gt;:&lt;/h5&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;from datetime import datetime


def is_new_year():
    &quot;&quot;&quot;
    Returns True when it&apos;s new year
    &quot;&quot;&quot;
    now = datetime.now()
    return now.month == 1 and now.day == 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Our objective is to write tests to validate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is_new_year()&lt;/code&gt; function.&lt;/p&gt;

&lt;h2 id=&quot;mocking-datetime&quot;&gt;Mocking datetime&lt;/h2&gt;

&lt;p&gt;This is one of the straightforward ways to change the time for your tests.
All you need to do is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;patch&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;datetime.datetime&lt;/code&gt; to do set desired datetime.
Let’s say our tests are in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test_new_year.py&lt;/code&gt;.&lt;/p&gt;

&lt;h5 id=&quot;source-code-for-test_new_yearpy&quot;&gt;Source code for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test_new_year.py&lt;/code&gt;:&lt;/h5&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;from datetime import datetime
from unittest import TestCase
from unittest.mock import patch

from new_year import is_new_year


class TestNewYear(TestCase):
    @patch(&quot;new_year.datetime&quot;)
    def test_is_new_year_true(self, mock_datetime):
        # test if is_new_year() returns True for first of January
        mock_datetime.now.return_value = datetime(2024, 1, 1)
        self.assertTrue(is_new_year())

    @patch(&quot;new_year.datetime&quot;)
    def test_is_new_year_false(self, mock_datetime):
        # test if is_new_year() returns False for second of January
        mock_datetime.now.return_value = datetime(2025, 1, 2)
        self.assertFalse(is_new_year())
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can run tests with the following command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;python3 -m unittest test_new_year
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In both of the test cases &lt;a href=&quot;https://docs.python.org/3/library/unittest.mock.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unittest.mock&lt;/code&gt;&lt;/a&gt; is used to change
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;datetime&lt;/code&gt; of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new_year&lt;/code&gt; module. But this can be cumbersome and
limiting when you use this in complex applications because this doesn’t change
the time across the whole application.&lt;/p&gt;

&lt;h2 id=&quot;freezegun&quot;&gt;Freezegun&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/spulec/freezegun&quot;&gt;Freezegun&lt;/a&gt; is a third-party Python library that allows test code
with time travelling. So, make sure that you install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;freezegun&lt;/code&gt; with&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pip install freezegun
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;source-code-for-test_new_yearpy-with-freezegun&quot;&gt;Source code for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test_new_year.py&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;freezegun&lt;/code&gt;:&lt;/h5&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;from freezegun import freeze_time
from unittest import TestCase

from new_year import is_new_year


class TestNewYear(TestCase):
    @freeze_time(&quot;2024-01-01&quot;)
    def test_is_new_year_true(self):
        # test if is_new_year() returns True for first of January
        self.assertTrue(is_new_year())

    @freeze_time(&quot;2024-01-02&quot;)
    def test_is_new_year_false(self):
        # test if is_new_year() returns False for second of January
        self.assertFalse(is_new_year())

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

&lt;p&gt;You can run tests with the following command similar to the above example:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;python3 -m unittest test_new_year
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Testing time-based functionality in Python can be done in a few different ways.
Using &lt;a href=&quot;https://docs.python.org/3/library/unittest.mock.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unittest.mock&lt;/code&gt;&lt;/a&gt; to patch &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;datetime&lt;/code&gt; is a basic method
but can be limiting for more complex applications. On the other hand,
&lt;a href=&quot;https://github.com/spulec/freezegun&quot;&gt;Freezegun&lt;/a&gt; provides a more robust solution for time travel in your
tests.&lt;/p&gt;

&lt;p&gt;Happy testing, and may your code be ever on time! :)&lt;/p&gt;

</description>
        <pubDate>Fri, 12 Jul 2024 12:00:00 +1200</pubDate>
        <link>https://fq.nz//blog/2024/07/12/python-time-travel</link>
        <guid isPermaLink="true">https://fq.nz//blog/2024/07/12/python-time-travel</guid>
        
        
        <category>python</category>
        
        <category>time</category>
        
        <category>testing</category>
        
        <category>unittest</category>
        
        <category>development</category>
        
      </item>
    
      <item>
        <title>Lightning Talk - PyPI Supply Chain Attacks</title>
        <description>&lt;p&gt;Here’s my lightning talk from &lt;a href=&quot;https://kiwipycon.nz/&quot;&gt;Kiwi PyCon XII&lt;/a&gt; that was held in
Waihōpai (Invercargill) last year.
The speech is about suplied chained attacks that affected &lt;a href=&quot;https://pypi.org/&quot;&gt;PyPI&lt;/a&gt; and how
they were mitigated.&lt;/p&gt;

&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube-nocookie.com/embed/KpomfsPtuC4?si=QWDdAomHLTVp7Zjp&amp;amp;start=2753&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;(Source: &lt;a href=&quot;https://www.youtube.com/watch?v=KpomfsPtuC4&quot;&gt;“Lightning Talks” - (Kiwi Pycon XI)&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;All the talks from Kiwi PyCon XI can be found &lt;a href=&quot;https://www.youtube.com/playlist?list=PLBGl1tVyiWQS-pJRrMVGuPGIsaZ8ZbbTO&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
        <pubDate>Sat, 03 Feb 2024 22:00:00 +1300</pubDate>
        <link>https://fq.nz//blog/2024/02/03/kiwi-pycon-2023-lighting-talk</link>
        <guid isPermaLink="true">https://fq.nz//blog/2024/02/03/kiwi-pycon-2023-lighting-talk</guid>
        
        
        <category>python</category>
        
        <category>lightning</category>
        
        <category>talk</category>
        
        <category>pypi</category>
        
      </item>
    
      <item>
        <title>Internet-Draft: draft-rathnayake-xml2rfc-unicode</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://github.com/ietf-tools/xml2rfc/&quot;&gt;xml2rfc&lt;/a&gt; is the tool used to generate
&lt;a href=&quot;https://en.wikipedia.org/wiki/Request_for_Comments&quot;&gt;RFC&lt;/a&gt; and
&lt;a href=&quot;https://en.wikipedia.org/wiki/Internet_Draft&quot;&gt;Internet-Drafts (I-D)&lt;/a&gt;.
xml2rfc converts XML documents to various formats like HTML, PDF and text.
The &lt;a href=&quot;https://datatracker.ietf.org/doc/draft-rathnayake-xml2rfc-unicode/&quot;&gt;draft-rathnayake-xml2rfc-unicode&lt;/a&gt;
is an experiment to see how various Unicode characters are represented in those
various output formats.&lt;/p&gt;

&lt;p&gt;I used a &lt;a href=&quot;https://github.com/kesara/xml2rfc-unicode/&quot;&gt;couple of Python scripts&lt;/a&gt;
to generate a list of Unicode characters and the Unicode blocks that they
belong to.
Then these were embedded in my draft XML with another Python script.&lt;/p&gt;

&lt;p&gt;The first revision I-D is available in various formats:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.ietf.org/archive/id/draft-rathnayake-xml2rfc-unicode-00.html&quot;&gt;HTML&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.ietf.org/archive/id/draft-rathnayake-xml2rfc-unicode-00.txt&quot;&gt;text&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/kesara/xml2rfc-unicode/raw/main/draft-rathnayake-xml2rfc-unicode-00.pdf&quot;&gt;PDF&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://datatracker.ietf.org/doc/pdf/draft-rathnayake-xml2rfc-unicode-00&quot;&gt;PDF (HTMLized)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Wed, 27 Dec 2023 23:23:23 +1300</pubDate>
        <link>https://fq.nz//blog/2023/12/27/draft-rathnayake-xml2rfc-unicode</link>
        <guid isPermaLink="true">https://fq.nz//blog/2023/12/27/draft-rathnayake-xml2rfc-unicode</guid>
        
        
        <category>internet-draft</category>
        
        <category>i-d</category>
        
        <category>draft</category>
        
        <category>xml2rfc</category>
        
        <category>ietf</category>
        
      </item>
    
      <item>
        <title>Lightning Talk - How Python can break the Internet</title>
        <description>&lt;p&gt;Here’s my lightning talk from &lt;a href=&quot;https://kiwipycon.nz/&quot;&gt;Kiwi PyCon XI&lt;/a&gt; that was held in
Ōtautahi (Christchurch) this year.
The speech is about how Python is a vital part of the tools used in
&lt;a href=&quot;https://www.ietf.org/&quot;&gt;IETF&lt;/a&gt;.&lt;/p&gt;

&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube-nocookie.com/embed/cNUkS8wbHZw?start=2654&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;(Source: &lt;a href=&quot;https://www.youtube.com/watch?v=cNUkS8wbHZw&quot;&gt;“Lightning Talks” - (Kiwi Pycon XI)&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;All the talks from Kiwi PyCon XI can be found &lt;a href=&quot;https://www.youtube.com/watch?v=KZcHnbnp18Q&amp;amp;list=PLBGl1tVyiWQT0Gq9NwrA2Rb7m16Sb_CRu&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
        <pubDate>Sun, 23 Oct 2022 23:00:00 +1300</pubDate>
        <link>https://fq.nz//blog/2022/10/23/kiwi-pycon-2022-lightning-talk</link>
        <guid isPermaLink="true">https://fq.nz//blog/2022/10/23/kiwi-pycon-2022-lightning-talk</guid>
        
        
        <category>python</category>
        
        <category>lightning</category>
        
        <category>talk</category>
        
        <category>ietf</category>
        
      </item>
    
      <item>
        <title>Visualization of Internet-Drafts</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://ietf.org/&quot;&gt;IETF (Internet Engineering Task Force)&lt;/a&gt; is a non-profit standards
organization that develops and promotes technical standards related to the
internet.
&lt;a href=&quot;https://github.com/kesara/visualize-ietf/&quot;&gt;Visualize IETF&lt;/a&gt; project is an attempt to visually present
how different &lt;a href=&quot;https://datatracker.ietf.org/area/&quot;&gt;areas&lt;/a&gt; have evolved and how authors have
contributed to Internet-Drafts (IDs) over time.
Visualizations were created using &lt;a href=&quot;https://gource.io/&quot;&gt;Gsource&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I have published all the visualizations that I created under this &lt;a href=&quot;https://www.youtube.com/playlist?list=PLuakzjxkt1oAjiOhkq66IWgspqnp_ZdfN&quot;&gt;YouTube
Playlist&lt;/a&gt;.
The source code of the project is hosted in GitHub under
&lt;a href=&quot;https://github.com/kesara/visualize-ietf/&quot;&gt;Visualize IETF&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here’s a sample visualization of how IDs were authored from January 2021 to
July 2021, This is clustered by &lt;a href=&quot;https://datatracker.ietf.org/area/&quot;&gt;areas&lt;/a&gt; and &lt;a href=&quot;https://datatracker.ietf.org/wg/&quot;&gt;working groups&lt;/a&gt;
that belong to the area.&lt;/p&gt;

&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube-nocookie.com/embed/3pmf486WPaQ&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;This project was created as a part of the &lt;a href=&quot;https://datatracker.ietf.org/meeting/111/proceedings&quot;&gt;IETF 111&lt;/a&gt; hackathon.
Here’s my presentation at the hackathon.
Slices are available &lt;a href=&quot;https://ietf-hackathon.github.io/ietf111-project-presentations/hackathon-presentation-id-visualizations.html#1&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube-nocookie.com/embed/fspjk0SHvBc?start=3097&amp;amp;&amp;amp;end=3407&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;(Source: &lt;a href=&quot;https://youtu.be/fspjk0SHvBc&quot;&gt;IETF111-HACKATHON-20210723-1900&lt;/a&gt;)&lt;/p&gt;

</description>
        <pubDate>Sat, 02 Oct 2021 15:02:02 +1300</pubDate>
        <link>https://fq.nz//blog/2021/10/02/visualization-of-internet-drafts</link>
        <guid isPermaLink="true">https://fq.nz//blog/2021/10/02/visualization-of-internet-drafts</guid>
        
        
        <category>data</category>
        
        <category>visualization</category>
        
        <category>IETF</category>
        
        <category>internet</category>
        
        <category>ID</category>
        
        <category>RFC</category>
        
      </item>
    
      <item>
        <title>Python Dependency Management</title>
        <description>&lt;p&gt;Dependency management in any language is hard, best way to avoid a dependency
hell is to avoid any dependencies. :) But that’s never practical.&lt;/p&gt;

&lt;p&gt;These are few suggestions to make dependency management easier. This blog
post is mainly focused on dependency management in a web applications.
Hope this will be useful.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;h2 id=&quot;tldr&quot;&gt;TL;DR&lt;/h2&gt;
  &lt;p&gt;Use venv and split out requirements similar to:&lt;/p&gt;

  &lt;table&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th&gt;Requirements file&lt;/th&gt;
        &lt;th&gt;Use&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requirements.txt&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;Direct dependencies of the application.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requirements.txt.lock&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;Version locked list of direct dependncies and their dependencies&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requirements.test.txt&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;Dependencies for testing&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requirements.sec.txt&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;Dependencies for security audits and tests&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requirements.dev.txt&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;Development tools and libraries for the project&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;always-use-venv&quot;&gt;Always use venv&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.python.org/3/library/venv.html&quot;&gt;Python virtual environment (venv)&lt;/a&gt;
module comes with your standard Python installation.
venv helps you to keep your development environment clean without leaking
Python libraries to other projects or environments. This also allows you to keep
different versions of Python and dependencies for testing.&lt;/p&gt;

&lt;p&gt;To create a new Python virtual environment use following command, this will
create a Python venv in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;venv&lt;/code&gt; directory.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;python -m venv venv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To activate your python venv:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;. venv/bin/activate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you want to deactivate your venv, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deactivate&lt;/code&gt; command.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I thought it’s good idea to mention about
&lt;a href=&quot;https://tox.readthedocs.io/en/latest/&quot;&gt;tox&lt;/a&gt; here. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tox&lt;/code&gt; is very useful tool
run tests for different Python environments. When you have a properly
configured &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tox.ini&lt;/code&gt; file and all the required Python versions that you need
to support installed. Just running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tox&lt;/code&gt; command will take care of things.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;use-requirementstxt-file-for-direct-dependencies&quot;&gt;Use requirements.txt file for direct dependencies&lt;/h2&gt;
&lt;p&gt;Use a &lt;a href=&quot;https://pip.pypa.io/en/latest/user_guide/#requirements-files&quot;&gt;requirements.txt&lt;/a&gt;
file for your direct dependencies, depending on your project requirements you
may add version information as well. But I like to keep the requirements.txt
file without any version information. Let’s call this &lt;em&gt;main requirements&lt;/em&gt; file
because there’ll be more.&lt;/p&gt;

&lt;p&gt;You can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip&lt;/code&gt; inside venv to install your dependencies.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pip install -r requirements.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It’s important to keep only the libraries that required to run your
application in this main requirements file. So don’t include libraries that’s
required for testing, deployment etc in this one.&lt;/p&gt;

&lt;h2 id=&quot;what-about-dependencies-of-direct-dependencies&quot;&gt;What about dependencies of direct dependencies?&lt;/h2&gt;
&lt;p&gt;Now it’s important to version lock dependencies for a production release.
It’s a bad idea to let your production environment decide which version to
install because that can lead to breaking changes or unintended side effects.
For that use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requirements.txt.lock&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Create this file after installing all your main requirements. You can use
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip freeze&lt;/code&gt; command for that.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pip freeze &amp;gt; requirements.txt.lock
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requirements.txt.lock&lt;/code&gt; must be used when you are deploying to a
production or test server or running tests on a CI/CD pipeline.
If you have to debug a production issue use this file to install dependencies,
so you have same versions of libraries as your production environment has.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Note that, some libraries depends on operating system and other external
ibraries, so this does not guarantee that your work environment will be 100%
imilar to production.&lt;/p&gt;

  &lt;p&gt;imilar to python version, pip version matters too. So it’s important to make
ure all environments use same pip version, and keep that up to date.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;what-about-testing-and-other-tools&quot;&gt;What about testing and other tools?&lt;/h2&gt;
&lt;p&gt;Keep your dependencies for testing in a seperate requirements file. Let’s call
that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requirements.test.txt&lt;/code&gt;. Your test dependencies like
&lt;a href=&quot;https://hypothesis.readthedocs.io/en/latest/&quot;&gt;hypothesis&lt;/a&gt;,
&lt;a href=&quot;https://github.com/joke2k/faker&quot;&gt;faker&lt;/a&gt; can go to that file.&lt;/p&gt;

&lt;p&gt;Keep other tools that you use for development like
&lt;a href=&quot;https://ipython.org/&quot;&gt;ipython&lt;/a&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requirements.dev.txt&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;I like to keep tools used for security vulnerability test in a seperate file
called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requirements.sec.txt&lt;/code&gt;, but this could be part of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requirements.test.txt&lt;/code&gt; as well. I like to keep it seperate because that allows
me to set up a seperate pipeline that only checks for security vulnerabilities
and dependency audits daily.&lt;/p&gt;

&lt;h2 id=&quot;security-frist&quot;&gt;Security frist!&lt;/h2&gt;
&lt;p&gt;Talking about security, it’s important audit your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requirements.txt.lock&lt;/code&gt; file
daily. You can use &lt;a href=&quot;https://pyup.io/safety/&quot;&gt;safety&lt;/a&gt; for that. When &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;safety&lt;/code&gt;
is installed it’s simple as running:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;safety check -r requirements.txt.lock
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Another good habit is to keep &lt;a href=&quot;https://pip.pypa.io/en/stable/&quot;&gt;pip&lt;/a&gt; up to
date. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip&lt;/code&gt; will let you know if there’s an update. You can upgrade &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip&lt;/code&gt;
with following command.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pip install --upgrade pip
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;constraints-files&quot;&gt;Constraints files&lt;/h2&gt;
&lt;p&gt;I haven’t used
&lt;a href=&quot;https://pip.pypa.io/en/latest/user_guide/#constraints-files&quot;&gt;Constraint files&lt;/a&gt;
in my projects so far. These files allows you to main a certain version of
a dependency through out.&lt;/p&gt;

&lt;p&gt;If you have a constraint file, you can use that with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip install&lt;/code&gt; as follow.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pip install -c constraints.txt -r requirements.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sat, 12 Jun 2021 08:09:23 +1200</pubDate>
        <link>https://fq.nz//blog/2021/06/12/python-dependency-management</link>
        <guid isPermaLink="true">https://fq.nz//blog/2021/06/12/python-dependency-management</guid>
        
        
        <category>python</category>
        
        <category>programming</category>
        
        <category>development</category>
        
        <category>security</category>
        
      </item>
    
      <item>
        <title>Web Application Security on a Budget</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://www.flickr.com/photos/kesara_rathnayake/8515398094/&quot;&gt;&lt;img src=&quot;/images/2020-11-30-img_0006_20130131_the_news_bangkok.png&quot; alt=&quot;The News - Suvarnabhumi Airport, Bangkok&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For a small business, information security mishap can be fatal blow to the
business. When you don’t have budget do annual penetration tests and keep a
dedicated set of engineers to maintain and look after your systems it might be
tough task to provide a secure online service to your customers.&lt;/p&gt;

&lt;p&gt;In this blog post, I’m providing some tips on keeping your online services
secured with on a very low budget.&lt;/p&gt;

&lt;h2 id=&quot;passwords&quot;&gt;Passwords&lt;/h2&gt;
&lt;p&gt;First things first use a &lt;a href=&quot;https://www.cert.govt.nz/individuals/guides/getting-started-with-cyber-security/keep-your-data-safe-with-a-password-manager/&quot;&gt;password manager&lt;/a&gt; to keep your passwords for different services like emails,
domain name, accounting software etc.&lt;/p&gt;

&lt;p&gt;Make sure that you use &lt;a href=&quot;https://www.cert.govt.nz/individuals/guides/getting-started-with-cyber-security/how-to-create-a-good-password/&quot;&gt;good password&lt;/a&gt;
for each service and it’s different from service to service. Never use the
same password for two different services.&lt;/p&gt;

&lt;p&gt;Other must do thing is to enable &lt;a href=&quot;https://www.cert.govt.nz/individuals/guides/getting-started-with-cyber-security/two-factor-authentication/&quot;&gt;Two Factor Authentication (2FA)&lt;/a&gt;
on all the services that provide it. These days most of major online services
provide 2FA, if the service that you use doesn’t provide 2FA, it might be a
good idea to move to a different provider that provide a better security.
&lt;a href=&quot;https://twofactorauth.org/&quot;&gt;twofactorauth.org&lt;/a&gt; has a list of major online
services that provide 2FA.&lt;/p&gt;

&lt;p&gt;Subscribe for &lt;a href=&quot;https://haveibeenpwned.com/NotifyMe&quot;&gt;Have I been pwned? Notify Me&lt;/a&gt;
service with all of your email addresses. This will provide you an alert if
any of your email addresses are linked in existing data breaches or newly
identified data breaches. Make sure to update your password if you got an
alert.&lt;/p&gt;

&lt;h2 id=&quot;static-website&quot;&gt;Static Website&lt;/h2&gt;
&lt;p&gt;Ask your self whether you need a dynamic web application or a just a static
website is enough. If you don’t update your content that often and your website
is just place to provide information to visitors, then small static website
will be enough.&lt;/p&gt;

&lt;p&gt;In that case consider using a service that provide small
static service or get a static website developed by credible developer or an
agency. If you are tech savvy you could make use of services like
&lt;a href=&quot;https://pages.github.com/&quot;&gt;GitHub Pages&lt;/a&gt; or &lt;a href=&quot;https://docs.gitlab.com/ee/user/project/pages/&quot;&gt;GitLab Pages&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Not having dynamic content, and sections such as user comments etc. greatly
minimizes some of the major attacks.&lt;/p&gt;

&lt;h2 id=&quot;dynamic-web-applications&quot;&gt;Dynamic Web Applications&lt;/h2&gt;
&lt;p&gt;If you provide a dynamic web application such as web shop, consider using a
reputable web shop provider. Similarly if you are after blog, use a reputable
blog service provider.&lt;/p&gt;

&lt;p&gt;Some of the security advantages that you get by going with an online web
application platform rather than getting a developer or agency to build you a
bespoke web application are:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Ongoing maintenance and security upgrades.&lt;/li&gt;
  &lt;li&gt;Better monitoring (from platform provider side).&lt;/li&gt;
  &lt;li&gt;Low chance of existing vulnerabilities. (Usually these services get frequent
penetration testing and has good bug bounty programs).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When using a web platform, make sure to be familiar with the security controls
provided by those services and use a good password and enable 2FA.&lt;/p&gt;

&lt;p&gt;Don’t install any “add-ons” / “plugins” unless your really have to. If you are
installing them make sure to do proper research on them and update them
promptly. Things to look out for in third party “add-ons” / “plugins” are:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Online reviews&lt;/li&gt;
  &lt;li&gt;Popularity&lt;/li&gt;
  &lt;li&gt;Plugin update frequency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Avoid using any plugins that hasn’t been updated in a while.&lt;/p&gt;

&lt;h2 id=&quot;domain-names&quot;&gt;Domain Names&lt;/h2&gt;
&lt;p&gt;Having a good domain name is important to your business but it is very
important that you keep your domain name with you without letting it expired.
As discussed above, using a good password and 2FA with your domain name
registrar or reseller is important. It is advisable to keep the domain name on
auto renew. Put a annual event in your calendar to check that auto renewal is
successful. Sometimes, a bad credit card, incorrect/old email address or
failure at the provider might end up your domain not getting renewed.&lt;/p&gt;

&lt;p&gt;Allowing your domain to expire and if a malicious party get hang of your
domain name, that will open a plethora of attacks on you, your customers and
providers.&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;Photograph: &lt;a href=&quot;https://www.flickr.com/photos/kesara_rathnayake/8515398094/&quot;&gt;“The News - Suvarnabhumi Airport, Bangkok” by Kesara Rathnayake&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Tue, 01 Dec 2020 12:54:23 +1300</pubDate>
        <link>https://fq.nz//blog/2020/12/01/web-application-security-on-a-budget</link>
        <guid isPermaLink="true">https://fq.nz//blog/2020/12/01/web-application-security-on-a-budget</guid>
        
        
        <category>information</category>
        
        <category>security</category>
        
        <category>infosec</category>
        
        <category>web</category>
        
        <category>applications</category>
        
      </item>
    
  </channel>
</rss>
