<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Andrew Channels Dexter Pinion</title><link>https://halfcooked.com/</link><description>Wherein I write something that you may like to read. Or not, it's up to you really.</description><atom:link href="https://halfcooked.com/rss.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><lastBuildDate>Wed, 28 Feb 2024 04:35:20 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Moving My Site</title><link>https://halfcooked.com/blog/2024/moving-my-site/</link><dc:creator>Andrew J Todd esq.</dc:creator><description>&lt;p&gt;I've recently dipped my toe into the murky waters of self hosting. Using some of the great information and encouragement provided by the &lt;a href="https://selfhosted.show/"&gt;Self Hosted podcast&lt;/a&gt; and numerous blogs I've been setting up and running a variety of applications and systems on my home network.&lt;/p&gt;
&lt;p&gt;The primary facilitators of this are &lt;a href="https://www.proxmox.com/en/"&gt;Proxmox&lt;/a&gt; and &lt;a href="https://www.docker.com/"&gt;Docker&lt;/a&gt;. I've used both as the new location for hosting this site. It used to run as an &lt;a href="https://httpd.apache.org/"&gt;Apache&lt;/a&gt; virtual site running on a &lt;a href="https://www.digitalocean.com"&gt;Digital Ocean&lt;/a&gt; droplet. But the traffic is &lt;em&gt;so&lt;/em&gt; low that having a dedicated server was definitely overkill.&lt;/p&gt;
&lt;p&gt;So I set up an &lt;a href="https://nginx.org/en/"&gt;Nginx&lt;/a&gt; container on a &lt;a href="https://www.proxmox.com/en/"&gt;Proxmox&lt;/a&gt; virtual machine by following &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-run-nginx-in-a-docker-container-on-ubuntu-22-04"&gt;this guide&lt;/a&gt; and simply pointed my static site generator - &lt;a href="https://getnikola.com/"&gt;Nikola&lt;/a&gt; - at the container's shared &lt;code&gt;html&lt;/code&gt; volume and I was up and running.&lt;/p&gt;
&lt;p&gt;Then I tweaked my &lt;code&gt;DNS&lt;/code&gt; settings and pointed them at my reverse proxy (running &lt;a href="https://nginxproxymanager.com/"&gt;Nginx Proxy Manager&lt;/a&gt;) which in turn points to the container I set up and away we go. It's a really simple and easy way to set up an isolated environment to run a simple web site like this one.&lt;/p&gt;</description><category>self-hosting</category><guid>https://halfcooked.com/blog/2024/moving-my-site/</guid><pubDate>Wed, 28 Feb 2024 04:32:59 GMT</pubDate></item><item><title>Jinja2 Templates in Django</title><link>https://halfcooked.com/blog/2022/jinja2-templates-in-django/</link><dc:creator>Andrew J Todd esq.</dc:creator><description>&lt;p&gt;Django supports 2 different template languages out of the box; Django Template Language (DTL) and &lt;a href="https://jinja2docs.readthedocs.io/en/stable/"&gt;Jinja2&lt;/a&gt;. The project documentation and most 3rd party tutorials deal exclusively with DTL. There is information on using Jinja2 templates in Django but it is scattered and a bit inconsistent. &lt;/p&gt;
&lt;p&gt;This is my attempt to provide a simple introduction to using Jinja2 templates in your Django project. To improve the reach of this document I'll restrict the examples to only use the sample Django project from the &lt;a href="https://docs.djangoproject.com/en/4.0/intro/tutorial01/"&gt;official tutorial&lt;/a&gt; and to make sure that I use the same terminology as that series of articles.&lt;/p&gt;
&lt;p&gt;If you've worked your way through the tutorial and have a working copy of the final code you should have a directory structure that looks like this;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Project folders 1" src="https://halfcooked.com/images/Django_tutorial_folders_01.png"&gt;&lt;/p&gt;
&lt;p&gt;Enabling Jinja2 templates for the &lt;code&gt;polls&lt;/code&gt; application is a 3 step process;&lt;/p&gt;
&lt;h5&gt;Enable Jinja2 Templates&lt;/h5&gt;
&lt;p&gt;Add an entry to the &lt;code&gt;TEMPLATES&lt;/code&gt; entry in the &lt;em&gt;project&lt;/em&gt; &lt;code&gt;settings.py&lt;/code&gt; file.  This will enable the Jinja2 template parser for your whole project. It should look like this;&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;TEMPLATES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;  
    &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="s"&gt;'BACKEND'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'django.template.backends.jinja2.Jinja2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
        &lt;span class="s"&gt;'DIRS'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;  
        &lt;span class="p"&gt;],&lt;/span&gt;  
        &lt;span class="s"&gt;'APP_DIRS'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
        &lt;span class="s"&gt;'OPTIONS'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
            &lt;span class="s"&gt;"environment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"polls.jinja2.environment"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
        &lt;span class="p"&gt;},&lt;/span&gt;  
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Don't remove the section that refers to the &lt;code&gt;DjangoTemplates&lt;/code&gt; backend as this will be needed by other applications in your project, particularly the &lt;code&gt;admin&lt;/code&gt; application.&lt;/p&gt;
&lt;h5&gt;Set up Your Jinja2 Environment&lt;/h5&gt;
&lt;p&gt;Create a &lt;code&gt;jinja2.py&lt;/code&gt; file under &lt;code&gt;django_tutorial/polls&lt;/code&gt;. This controls which global functions are available to your Jinja2 templates. A simple version will look like this&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;jinja2&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Environment&lt;/span&gt;  
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.urls&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;  
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.templatetags.static&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;static&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
    &lt;span class="n"&gt;env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;globals&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
        &lt;span class="s2"&gt;"static"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;static&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
        &lt;span class="s2"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;  
    &lt;span class="p"&gt;})&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h5&gt;Create a Folder for your Jinja2 Templates&lt;/h5&gt;
&lt;p&gt;By default (and because we set &lt;code&gt;APP_DIRS&lt;/code&gt; to &lt;code&gt;True&lt;/code&gt; in the Jinja2 template configuration in our &lt;code&gt;settings.py&lt;/code&gt;) at run time Django will chose which template backend to use based on the name of the directory any template file is located in. The default for Jinja2 templates is &lt;code&gt;&amp;lt;app name&amp;gt;/jinja2/&amp;lt;app name&amp;gt;&lt;/code&gt;. So for our &lt;code&gt;polls&lt;/code&gt; application we need a folder called &lt;code&gt;django_tutorial/polls/jinja2/polls&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Project folders 2" src="https://halfcooked.com/images/Django_tutorial_folders_02.png"&gt;&lt;/p&gt;
&lt;p&gt;Be careful when mixing and matching Jinja2 and Django templates in your own applications though. As a general rule it's better to use one template backend for all of the pages in your application. If you do mix and match make sure that you give each template a distinct name, if only to avoid confusing yourself when you are working on your project.&lt;/p&gt;
&lt;p&gt;Note that you can specify your own location for Jinja2 (and Django) templates on a project or application basis but that's beyond the scope of this article.&lt;/p&gt;</description><category>django</category><category>python</category><category>web</category><guid>https://halfcooked.com/blog/2022/jinja2-templates-in-django/</guid><pubDate>Sun, 30 Jan 2022 02:51:08 GMT</pubDate></item><item><title>Back to Blogging</title><link>https://halfcooked.com/blog/2020/back-to-blogging/</link><dc:creator>Andrew J Todd esq.</dc:creator><description>&lt;p&gt;I haven't stopped, I've just stopped writing here. So now it's time to attempt a comeback, and not to be too hard on myself if this is a once in a while proposition. I haven't been working on a big secret project, or at least nothing that will be ready to reveal for a decade or two. Most of my technology and free time has been spent on what I would call 'tinkering'. I have tried out a lot of tools, technologies and small experiments but nothing has stuck.&lt;/p&gt;
&lt;p&gt;So rather than wait for something serious and significant to write about I'm going to try and keep track of the things I have been trying in the hope that they will help other people in similar situations or act as a deterrent from wasting your time on such frivolous pursuits.&lt;/p&gt;
&lt;p&gt;To that end I'm going to attempt to keep some &lt;a href="https://weeknot.es/"&gt;weeknotes&lt;/a&gt; here, inspired by but probably not nearly as useful as those published by the likes of &lt;a href="https://simonwillison.net/tags/weeknotes/"&gt;Simon Willison&lt;/a&gt; and &lt;a href="https://revdancatt.com/weeknotes"&gt;Dan Catt&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For reference the subjects I've spent most time fiddling about with are &lt;a href="https://en.wikipedia.org/wiki/Markdown"&gt;Markdown&lt;/a&gt; note taking tools, various &lt;a href="https://www.python.org"&gt;Python&lt;/a&gt; libraries, and trying to run my own services on my own server very much in the vein of Danny O'Brien's &lt;a href="https://www.oblomovka.com/wp/2008/07/24/video-from-living-on-the-edge-opentech-2008/"&gt;living on the edge&lt;/a&gt; discussions from a mere 12 years ago. Who says I'm not up to date?&lt;/p&gt;</description><category>General</category><guid>https://halfcooked.com/blog/2020/back-to-blogging/</guid><pubDate>Wed, 12 Aug 2020 05:07:39 GMT</pubDate></item><item><title>DNS Configuration</title><link>https://halfcooked.com/blog/2017/dns-configuration/</link><dc:creator>Andrew J Todd esq.</dc:creator><description>&lt;p&gt;This post answers the question "how do I host my email at one provider and my web site at another?". In particular it shows how to set up DNS at your domain name registrar, email at &lt;a href="https://www.fastmail.com"&gt;Fastmail&lt;/a&gt; and web hosting at &lt;a href="https://www.webfaction.com"&gt;WebFaction&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Most of the how to DNS configuration guides on the web show how to point to a single hosting provider for web, email and other services. I'm awkward and wanted to separate my email from web hosting. So by a little trial and error I came up with this set up for my personal domain. &lt;/p&gt;
&lt;p&gt;First at your domain registrar (I use &lt;a href="https://www.hover.com"&gt;hover&lt;/a&gt;) set the domain namervers to Fastmail, I've used 2 of their name servers.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Nameservers" src="https://halfcooked.com/images/DNS_Hover_Nameservers.png"&gt;&lt;/p&gt;
&lt;p&gt;This delegates control of all DNS activity for the domain to &lt;a href="https://www.fastmail.com"&gt;Fastmail&lt;/a&gt;. Without any other changes this will allow Fastmail to manage email and serve a limited web site from their hosting option. I choose to host my web site at &lt;a href="https://www.webfaction.com"&gt;WebFaction&lt;/a&gt; and so to delegate this from &lt;a href="https://www.fastmail.com"&gt;Fastmail&lt;/a&gt; we use their domain configuration dashboard and set up DNS 'A' records to point to my &lt;a href="https://www.webfaction.com"&gt;WebFaction&lt;/a&gt; host.&lt;/p&gt;
&lt;p&gt;&lt;img alt="A records" src="https://halfcooked.com/images/DNS_A_records.png"&gt;&lt;/p&gt;
&lt;p&gt;The final step is to configure &lt;a href="https://www.webfaction.com"&gt;WebFaction&lt;/a&gt; to accept and serve your domain. If they don't recognise incoming web traffic you won't be able to server a web site on your domain. Here's mine set up in domains section of the &lt;a href="https://www.webfaction.com"&gt;WebFaction&lt;/a&gt; control panel.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Control panel" src="https://halfcooked.com/images/DNS_control_panel.png"&gt;&lt;/p&gt;</description><category>General</category><guid>https://halfcooked.com/blog/2017/dns-configuration/</guid><pubDate>Tue, 06 Jun 2017 00:55:03 GMT</pubDate></item><item><title>RSS Readers in 2016</title><link>https://halfcooked.com/blog/2017/rss-readers-in-2016/</link><dc:creator>Andrew J Todd esq.</dc:creator><description>&lt;p&gt;After the great &lt;a href="http://lifehacker.com/google-reader-is-shutting-down-here-are-the-best-alter-5990456"&gt;Google Reader shutdown&lt;/a&gt; of 2013 I switched my feed reading to a self-hosted
instance of &lt;a href="http://feedafever.com/"&gt;Fever&lt;/a&gt; and I've been a happy user ever since. I didn't mind 
that it wasn't open source, I was glad to spend the money to support a developer building a great
product. Sadly now that support and developed &lt;a href="http://shauninman.com/archive/2016/12/24/goodbye_mint_goodbye_fever"&gt;has ended&lt;/a&gt;. I'd like to thank &lt;a href="http://shauninman.com/"&gt;Shaun Inman&lt;/a&gt; for a great product. The end
of development and support for Fever don't necessarily mean that it will stop working at any time
in the near future. But I took this as an opportunity to look around at the
state of the RSS reader world and see if there isn't a better tool for me to use now and for the
future.&lt;/p&gt;
&lt;p&gt;My requirements are simple. It must run on a server that I control, be accessible using a reasonably
modern web browser and support import and export of feed listings via &lt;a href="http://dev.opml.org/"&gt;OPML&lt;/a&gt;. Theere are bonus marks if the &lt;a href="https://halfcooked.com/blog/2017/rss-readers-in-2016/"&gt;Fever API&lt;/a&gt; is supported (I've got &lt;a href="https://halfcooked.com/blog/2017/rss-readers-in-2016/"&gt;Reeder&lt;/a&gt; running on my iPad) and 
for ease of installation and use. I'm not a sophisticated feed reader but I've accumulated quite
a collection of sites that I follow over the years. Fever is currently following 370 feeds but I can 
use any transition as an opportunity to trim away the dead wood.&lt;/p&gt;
&lt;p&gt;After a little research and with some help from &lt;a href="https://opensource.com/life/13/3/eight-open-source-rss-feed-readers"&gt;OpenSource.com&lt;/a&gt; I narrowed my search to three possible solutions: &lt;a href="http://selfoss.aditu.de/"&gt;selfoss&lt;/a&gt;, &lt;a href="https://miniflux.net/"&gt;miniflux&lt;/a&gt; and &lt;a href="https://tt-rss.org/gitlab/fox/tt-rss/wikis/home"&gt;Tiny Tiny RSS&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;My evaluation strategy was pretty simple - install the tool on an Ubuntu virtual machine and if
it looks promising do a fresh install on my web server and try the tool for size for a few days.&lt;/p&gt;
&lt;h3&gt;Selfoss&lt;/h3&gt;
&lt;p&gt;This topped a few of the searches I did and was the first solution I installed. Well, I say
that but I haven't managed to install it on my VM. I got to the stage of posting to the forum
asking about error messages that reported missing PHP .so files before I gave up. In this 
particular case it looks to me like the install expected PHP 5 but on the Ubuntu 16.04 the
default is PHP 7. I may be wrong, I'm certainly no PHP guru, but clear installation requirements
and instructions are nice. I may revisit selfoss again and see if I can't get over my
installation problems.&lt;/p&gt;
&lt;h3&gt;Miniflux&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://miniflux.net/"&gt;Miniflux&lt;/a&gt; takes the &lt;a href="http://scripting.com/2014/06/02/whatIsARiverOfNewsAggregator.html"&gt;river of news&lt;/a&gt; 
approach and applies it to a minimalist presentation. Installation was fairly straight forward
and I managed to import my feed collection quite quickly. The folder structure that I had set
up in Fever didn't make the transition - it isn't part of the OPML contents - so I took the
opportunity to trim my feed list and put them into a small number of groups.&lt;/p&gt;
&lt;p&gt;Updating the feeds is simple in the web UI - just press the 'refresh all' link on the 
subscriptions page. Then go to the 'unread' page and scroll through the articles. There are
some nice simple keyboard shortcuts to aid navigation and reading.&lt;/p&gt;
&lt;p&gt;There are 2 puzzles I still haven't cracked with Miniflux. I can't get the automated feed
refresh working - probably something to do with the way I have set up PHP - and I still
haven't found out what the 'groups' are used for. Apart from this minor quirks I am liking
the philosophy and execution of miniflux and I think it's going to be my feed reader from 
now on.&lt;/p&gt;
&lt;h3&gt;Tiny Tiny RSS&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://tt-rss.org"&gt;Tiny Tiny RSS&lt;/a&gt; has been around for a few years and receives rave reviews
on the web. Installation on my virtual machine was pretty straight forward and I had it up
and running without any problems. The interface is more complex than Miniflux, and even than
Fever, with nested folders of feeds and a nice display of each article.&lt;/p&gt;
&lt;p&gt;Where I struggled with Tiny Tiny RSS was refreshing the feeds. The documentation says that 
this is best done via a cron job but I couldn't get the command working. I'm also not mad
keen on running a PostgreSQL server on my web host as I'm not knowledgeable enough to keep
it running securely.&lt;/p&gt;
&lt;p&gt;So for the time being I'm going with Miniflux&lt;/p&gt;</description><category>General</category><guid>https://halfcooked.com/blog/2017/rss-readers-in-2016/</guid><pubDate>Tue, 10 Jan 2017 04:56:47 GMT</pubDate></item><item><title>Simple Log</title><link>https://halfcooked.com/blog/2016/simple-log/</link><dc:creator>Andrew J Todd esq.</dc:creator><description>&lt;p&gt;I found myself putting the same few lines of code at the top of every script or module that I wrote. 
 It went something like this:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;logging&lt;/span&gt;
&lt;span class="n"&gt;MESSAGE_FORMAT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;%(asctime)s&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;%(levelname)s&lt;/span&gt;&lt;span class="s2"&gt;:: &lt;/span&gt;&lt;span class="si"&gt;%(message)s&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;DATE_FORMAT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"%Y.%m.&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s2"&gt; %T"&lt;/span&gt;
&lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setLevel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;formatter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Formatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MESSAGE_FORMAT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DATE_FORMAT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StreamHandler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setFormatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Because the default simple logging provided by the standard library &lt;code&gt;logging&lt;/code&gt; package doesn't do everything I'd like. I prefer that messages contain the time that they were generated. I prefer that the default logging level is set to &lt;code&gt;INFO&lt;/code&gt;. I don't really care to see the log name in each log message.&lt;/p&gt;
&lt;p&gt;When I built bigger applications I found myself putting this code in a &lt;code&gt;log.py&lt;/code&gt; file and 
including it with the application source code. Then I wanted to change the log format. Which
meant editing quite a few copies of the same file. So I decided that was a bad idea and I 
would turn my simple few lines of code into a Python module and publish it on &lt;a href="https://pypi.python.org/pypi"&gt;PyPi&lt;/a&gt;.
That way I could include a single copy of the code in each of my modules or applications with 
a simple &lt;code&gt;pip install&lt;/code&gt; command.&lt;/p&gt;
&lt;p&gt;The last time I did some serious packaging work this all rather tricky but thanks to the most
excellent work of the &lt;a href="https://www.pypa.io/"&gt;Python Packaging Authority&lt;/a&gt; publishing your own
Python module is a breeze these days.&lt;/p&gt;
&lt;p&gt;So say hello to &lt;code&gt;simple_log&lt;/code&gt;. It's available from PyPI now - &lt;a href="https://pypi.python.org/pypi/simple-log/"&gt;https://pypi.python.org/pypi/simple-log/ &lt;/a&gt; &lt;/p&gt;
&lt;p&gt;The documentation is on this site - &lt;a href="http://halfcooked.com/code/simple_log/"&gt;http://halfcooked.com/code/simple_log/&lt;/a&gt; and the source code lives on BitBucket at &lt;a href="https://bitbucket.org/andy47/simplelog"&gt;https://bitbucket.org/andy47/simplelog&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It's designed to be a simple log module that can be incorporated in any Python application and
used as simply as:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;simple_log&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_log&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_log&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Information message'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mf"&gt;2016.12.12&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;Information&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;No more worrying about streams and formatters just a nice simple way to get a log object and 
log messages from your code. The code is licensed under the &lt;a href="https://opensource.org/licenses/MIT"&gt;MIT license&lt;/a&gt; 
so corrections, additions and praise are always welcome.&lt;/p&gt;</description><category>python</category><guid>https://halfcooked.com/blog/2016/simple-log/</guid><pubDate>Sun, 11 Dec 2016 23:00:00 GMT</pubDate></item><item><title>Generating Diceware Passwords in Python</title><link>https://halfcooked.com/blog/2015/03/30/generating-diceware-passwords-in-python/</link><dc:creator>Andrew J Todd esq.</dc:creator><description>&lt;p&gt;Today I'm going back to a theme from a post I wrote &lt;a href="http://halfcooked.com/blog/2014/04/15/generating-reasonable-passwords-with-python/"&gt;last year&lt;/a&gt;
 and looking at generating passwords with my favourite programming language. A &lt;a href="https://twitter.com/brunns/status/581443843322593280"&gt;tweet&lt;/a&gt; 
 from Simon Brunning pointed me to &lt;a href="https://firstlook.org/theintercept/2015/03/26/passphrases-can-memorize-attackers-cant-guess/"&gt;Micah Lee's article at The Intercept&lt;/a&gt;
and my first thought was to write a function to do this in &lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt;. So here it is; &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;random&lt;/span&gt;
&lt;span class="n"&gt;word_dict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="n"&gt;passphrase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'diceware.wordlist.andy.txt'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readlines&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;word_dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;word_count&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;this_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;digit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;randint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;this_index&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;digit&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;passphrase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word_dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;this_index&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;passphrase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In terribly bad form I've hard coded the diceware word list file name. I took the &lt;a href="http://world.std.com/~reinhold/diceware.wordlist.asc"&gt;English word list&lt;/a&gt;
and converted it to a plain text file for easier processing. The original will probably work just as well, I just haven't tested it.&lt;/p&gt;</description><category>python</category><guid>https://halfcooked.com/blog/2015/03/30/generating-diceware-passwords-in-python/</guid><pubDate>Mon, 30 Mar 2015 10:48:22 GMT</pubDate></item><item><title>Teaching an old dog to Fish</title><link>https://halfcooked.com/blog/2014/10/10/teaching-an-old-dog-to-fish/</link><dc:creator>Andrew J Todd esq.</dc:creator><description>&lt;p&gt;Inspired by the recent furore around &lt;a href="https://en.wikipedia.org/wiki/Shellshock_%28software_bug%29"&gt;Shellshock&lt;/a&gt;
I decided that it was time to try an alternative to &lt;a href="https://www.gnu.org/software/bash/"&gt;bash&lt;/a&gt;
By the very grown up process of shutting my eyes and poking my finger at the results of a &lt;a href="http://duckduckgo.com/"&gt;search&lt;/a&gt;
for "shell" I ended up at &lt;a href="http://fishshell.com/"&gt;fish shell&lt;/a&gt;, described by the project as "a command line shell for the 90s". I'm presuming that this means the 1990s and is not a minimum age requirement.&lt;/p&gt;
&lt;p&gt;I'm quite enjoying it so far but the missing piece for me was something equivalent to the very useful &lt;a href="http://virtualenvwrapper.readthedocs.org/en/latest/"&gt;virtualenvwrapper&lt;/a&gt;. 
Luckily for me someone else has already had this problem and wrote &lt;a href="https://github.com/adambrenecki/virtualfish/"&gt;virtual fish&lt;/a&gt;.
For which many thanks. I did have a little trouble with installation and configuration. I'm sure that this was entirely my own fault but as a reminder for me and anyone else who stumbles on this here is what I did.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Downloaded &lt;code&gt;virtual.fish&lt;/code&gt; from the &lt;a href="https://github.com/adambrenecki/virtualfish/releases"&gt;Github repo&lt;/a&gt; to &lt;code&gt;~/bin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Because I don't use &lt;code&gt;~/.virtualenvs&lt;/code&gt; to store my virtual environments I added &lt;code&gt;set -x VIRTUALFISH_HOME ~/Work/envs/&lt;/code&gt; to my &lt;code&gt;.config/fish/fish.config&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;Included the currently active virtual environment name in my prompt by following the &lt;a href="http://virtualfish.readthedocs.org/en/latest/install.html#customizing-your-fish-prompt"&gt;instructions&lt;/a&gt;. A trap for young players is to make sure that you do &lt;code&gt;funcsave fish_prompt&lt;/code&gt; as instructed. I missed this out the first couple of times and kept wondering why my prompt was wrong.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: Thanks for the comments. bronsen - yes I do source &lt;code&gt;virtual.fish&lt;/code&gt; in my &lt;code&gt;config.fish&lt;/code&gt;. Or at least I did until jl pointed me at &lt;a href="https://github.com/berdario/pew"&gt;Pew&lt;/a&gt;. Now I've switched to that from virtualenvwrapper and virtual.fish and I must say that it works like a dream. Thanks both for taking the time to leave a comment.&lt;/p&gt;</description><category>fish</category><guid>https://halfcooked.com/blog/2014/10/10/teaching-an-old-dog-to-fish/</guid><pubDate>Fri, 10 Oct 2014 14:38:47 GMT</pubDate></item><item><title>Generating Reasonable Passwords with Python</title><link>https://halfcooked.com/blog/2014/04/15/generating-reasonable-passwords-with-python/</link><dc:creator>Andrew J Todd esq.</dc:creator><description>&lt;p&gt;Thanks to a certain recent &lt;a href="https://halfcooked.com/blog/2014/04/15/generating-reasonable-passwords-with-python/" title="http://heartbleed.com/"&gt;Open SSL bug&lt;/a&gt; there's been a lot of attention paid to passwords in the media. I've been using &lt;a href="http://www.keepassx.org"&gt;KeePassX&lt;/a&gt; to manage my passwords for the last few years so it's easy for me to find accounts that I should update. It's also a good opportunity to use passwords that are stronger than words such as 'banana'.&lt;/p&gt;
&lt;p&gt;My problem is that I have always resisted the generation function in &lt;a href="http://www.keepassx.org"&gt;KeePassX&lt;/a&gt; because the resulting strings are very hard to remember and transcribe. This isn't an issue if you always use one machine but I tend to chop and change and don't always have my password database on the machine I'm using. I usually have a copy on my phone but successfully typing 'Gh46^f27EEGR1p{' is a hit and miss affair for me. So I prefer passwords that are long but easy to remember, not unlike the advice from &lt;a href="http://xkcd.com/936/"&gt;XKCD&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Which leaves a problem. Given that I now have to change quite a lot of passwords how can I create suitably random passwords that aren't too difficult to remember or transcribe? Quite coincidentally I read an article titled &lt;a href="http://invert.svbtle.com/using-vim-as-a-password-manager"&gt;Using Vim as a passowrd manager&lt;/a&gt;. The advice within it is quite sound and at the bottom there is a Python function to generate a password from word lists (in this case the system dictionary). This does a nice job with the caveat that as I understand it from a cryptographic standpoint the passwords it creates are not that strong. But useful enough for sites which aren't my bank or primary email. For those I'm using stupidly long values generated from &lt;a href="http://www.keepassx.org"&gt;KeePassX&lt;/a&gt;. When I tried the Python function on my machine there was one drawback, it doesn't work in Python 3. This is because the use of 'map' is discouraged in Python 3. But that's alright because I can replace it with one of my favourite Python constructs - the list comprehension. Here is an updated version of invert's function that works in Python 3. Use at your own risk.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_password&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;random&lt;/span&gt;
    &lt;span class="c1"&gt;# Make a list of all of the words in our system dictionary&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/usr/share/dict/words'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readlines&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
    &lt;span class="c1"&gt;# Pick 2 random words from the list&lt;/span&gt;
    &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'-'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capitalize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;# Remove any apostrophes&lt;/span&gt;
    &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Add a random number to the end of our password&lt;/span&gt;
    &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;randint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9999&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</description><category>python</category><guid>https://halfcooked.com/blog/2014/04/15/generating-reasonable-passwords-with-python/</guid><pubDate>Tue, 15 Apr 2014 16:33:00 GMT</pubDate></item><item><title>My Career</title><link>https://halfcooked.com/blog/2014/03/28/my-career/</link><dc:creator>Andrew J Todd esq.</dc:creator><description>&lt;p&gt;The next time anyone asks me what I do for a living I'm just going to point them to this YouTube video.&lt;/p&gt;
&lt;iframe width="560" height="315" src="//www.youtube.com/embed/BKorP55Aqvg" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;Found on the twitters thanks to &lt;a href="http://www.linkedin.com/in/nickhodge"&gt;Nick Hodge&lt;/a&gt; and &lt;a href="https://twitter.com/girlgerms"&gt;Jess Dodson&lt;/a&gt;
.&lt;/p&gt;</description><category>General</category><guid>https://halfcooked.com/blog/2014/03/28/my-career/</guid><pubDate>Fri, 28 Mar 2014 11:14:28 GMT</pubDate></item></channel></rss>