<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
  <title type="text">L'Alpiniste</title>
  <id>http://blog.projectfondue.com/feed.atom</id>
  <updated>2010-01-21T23:51:57Z</updated>
  <link href="http://blog.projectfondue.com/" />
  
  <subtitle type="text">The blog of the Project Fondue Team</subtitle>
  <generator uri="http://zine.pocoo.org/" version="0.1.2">Zine</generator>
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/projectfondue/posts" /><feedburner:info uri="projectfondue/posts" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry xml:base="http://blog.projectfondue.com/feed.atom">
    <title type="text">Getting an Early Warning of Low Disk Space</title>
    <id>tag:blog.projectfondue.com,2010-01-21:/entry;2010/1/21/poor-man-s-low-disk-space-warning-with-python</id>
    <updated>2010-01-21T23:51:57Z</updated>
    <published>2010-01-21T23:11:00Z</published>
    <link href="http://feedproxy.google.com/~r/projectfondue/posts/~3/Xu8v5whNdbI/getting-an-early-warning-of-low-disk-space" />
    <author>
      <name>Stuart Colville</name>
    </author>
    <content type="html">&lt;div id="keeping-an-eye-on-disk-space" class="section"&gt;
&lt;h2&gt;Keeping an eye on Disk Space&lt;/h2&gt;
&lt;p&gt;Running out of disk space is not a good situation to be in. Services that run out of disk space can cause your server to blow up in a very short space of time. As a result of that it's a good idea to get an early warning that your machine is on it's way to running out of disk space. This script is a noddy way to get that insight with minimum effort.&lt;/p&gt;
&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="c"&gt;# -*- coding: utf-8 -*-&lt;/span&gt;

&lt;span class="sd"&gt;"""&lt;/span&gt;
&lt;span class="sd"&gt;Disk Space&lt;/span&gt;
&lt;span class="sd"&gt;Simple class for working out the free disk space on a system&lt;/span&gt;

&lt;span class="sd"&gt;by Stuart Colville http://muffinresearch.co.uk&lt;/span&gt;
&lt;span class="sd"&gt;License: http://www.opensource.org/licenses/mit-license.php&lt;/span&gt;

&lt;span class="sd"&gt;"""&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;math&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DiskSpace&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;

    &lt;span class="sd"&gt;"""Free Disk Space"""&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;"""Init class and retrieves disk space info"""&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;disk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;statvfs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;has_free_space&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;"""Bool returns true if remaining space is above limit %"""&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;float&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="n"&gt;percent_free&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;percent_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;"""Gets the amount of space left as a percentage"""&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bytes_capacity&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
                                                &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bytes_free&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bytes_capacity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;"""Returns the total capacity in bytes"""&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;disk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f_frsize&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;disk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f_blocks&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bytes_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;"""Returns the free space in bytes"""&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;disk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f_frsize&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;disk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f_bavail&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bytes_used&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;"""Returns the used space in bytes"""&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;disk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f_frsize&lt;/span&gt; &lt;span class="o"&gt;*&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="n"&gt;disk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f_blocks&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;
                                                   &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;disk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f_bavail&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nd"&gt;@staticmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;humanize_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kilo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

        &lt;span class="sd"&gt;"""Humanizes bytes&lt;/span&gt;

&lt;span class="sd"&gt;        See http://en.wikipedia.org/wiki/Kilobyte for info on the&lt;/span&gt;
&lt;span class="sd"&gt;        different ways to interpret whether a kilobyte is 1,024 bytes&lt;/span&gt;
&lt;span class="sd"&gt;        or 1,000 bytes&lt;/span&gt;

&lt;span class="sd"&gt;        """&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;kilo&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mf"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"KiB"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"MiB"&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"GiB"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"TiB"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c"&gt;# fallback&lt;/span&gt;
            &lt;span class="n"&gt;kilo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1000&lt;/span&gt;
            &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"KB"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"MB"&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"GB"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"TB"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;kilo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;kilo&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kilo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="si"&gt;%.2F%s&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;kilo&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kilo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kilo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="si"&gt;%.2F%s&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kilo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kilo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kilo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="si"&gt;%.2F%s&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kilo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kilo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kilo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="si"&gt;%.2F%s&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kilo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;3&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id="example" class="section"&gt;
&lt;h2&gt;Example&lt;/h2&gt;
&lt;p&gt;Here's a quick example of how this can be used in practice&lt;/p&gt;
&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="c"&gt;#!/usr/bin/env python&lt;/span&gt;
&lt;span class="c"&gt;# -*- coding: utf-8 -*-&lt;/span&gt;

&lt;span class="sd"&gt;"""Simple example command line usage:&lt;/span&gt;

&lt;span class="sd"&gt;Usage: ./check_disk_space.py &amp;lt;percentage free space&amp;gt;&lt;/span&gt;

&lt;span class="sd"&gt;e.g:&lt;/span&gt;

&lt;span class="sd"&gt;$ ./check_disk_space.py 30&lt;/span&gt;
&lt;span class="sd"&gt;Running low on disk space. 20.0% remaining (Warning Threshold: 30%)&lt;/span&gt;
&lt;span class="sd"&gt;Total: 115.13GB&lt;/span&gt;
&lt;span class="sd"&gt;Used:  92.35GB&lt;/span&gt;
&lt;span class="sd"&gt;Avail: 22.77GB&lt;/span&gt;

&lt;span class="sd"&gt;The idea would be to put this in a Cron Job and have it email you when&lt;/span&gt;
&lt;span class="sd"&gt;the free disk space is lower than "n" percent.&lt;/span&gt;

&lt;span class="sd"&gt;"""&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;

&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'../'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;diskspace&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DiskSpace&lt;/span&gt;

&lt;span class="n"&gt;ds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DiskSpace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;perc_arg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;1&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;span class="n"&gt;percent_limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;perc_arg&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="mf"&gt;20&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;ds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;has_free_space&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;percent_limit&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;"Running low on disk space. &lt;/span&gt;&lt;span class="si"&gt;%s%%&lt;/span&gt;&lt;span class="s"&gt; remaining "&lt;/span&gt;\
       &lt;span class="s"&gt;"(Warning Threshold: &lt;/span&gt;&lt;span class="si"&gt;%s%%&lt;/span&gt;&lt;span class="s"&gt;)"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;percent_free&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;percent_limit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;"Total: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;ds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;humanize_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bytes_capacity&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mf"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;"Used:  &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;ds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;humanize_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bytes_used&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mf"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;"Avail: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;ds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;humanize_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bytes_free&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mf"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This last file can be saved as check_disk_space.py and made executable with:&lt;/p&gt;
&lt;div class="syntax"&gt;&lt;pre&gt;chmod +x check_disk_space.py
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;All you then need to do is add a crontab entry and define the limit at which you want to be warned of impending disk space running out.&lt;/p&gt;
&lt;div class="syntax"&gt;&lt;pre&gt;MAILTO=systems@yourdomain.com
0 */2 * * * /path/to/file/free_disk_space 15
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This example will check the space every 2 hours and will email you when the remaining disk space drops below 15%.&lt;/p&gt;
&lt;p&gt;A Branch of these files is available here: &lt;a href="http://code.projectfondue.com/diskspace/trunk/files/head:/diskspace/" class="reference external"&gt;http://code.projectfondue.com/diskspace/trunk/files/head:/diskspace/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Suggestions for improvement are always welcome.&lt;/p&gt;
&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/projectfondue/posts/~4/Xu8v5whNdbI" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.projectfondue.com/2010/1/21/getting-an-early-warning-of-low-disk-space</feedburner:origLink></entry>
  <entry xml:base="http://blog.projectfondue.com/feed.atom">
    <title type="text">Loggerhead and mod_wsgi</title>
    <id>tag:blog.projectfondue.com,2009-11-26:/entry;2009/11/26/loggerhead-and-mod-wsgi</id>
    <updated>2009-11-27T09:14:52Z</updated>
    <published>2009-11-26T21:55:00Z</published>
    <link href="http://feedproxy.google.com/~r/projectfondue/posts/~3/UOF8O7gmIR8/loggerhead-and-mod-wsgi" />
    <author>
      <name>Stuart Colville</name>
    </author>
    <content type="html">&lt;p&gt;Currently &lt;a href="https://edge.launchpad.net/loggerhead" class="reference external"&gt;loggerhead&lt;/a&gt; defaults to using pasteserver out of the box, which means you have to proxy this with Apache if you don't want to use pasteserver directly. Instead of doing that we went the route of setting up Loggerhead under apache with mod_wsgi.&lt;/p&gt;
&lt;p&gt;Here's the wsgi file to set-up the application.&lt;/p&gt;
&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="n"&gt;BZR_SERVE_DIR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'THE_DIR_CONTAINING_YOUR_BRANCHES_HERE'&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;paste.httpexceptions&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HTTPExceptionHandler&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;loggerhead.apps.transport&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BranchesFromTransportRoot&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;loggerhead.apps.error&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ErrorHandlerApp&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;loggerhead.config&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;LoggerheadConfig&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;paste.deploy.config&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PrefixMiddleware&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;bzrlib.plugin&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_plugins&lt;/span&gt;

&lt;span class="n"&gt;load_plugins&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;LoggerheadConfig&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BranchesFromTransportRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BZR_SERVE_DIR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PrefixMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HTTPExceptionHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;application&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ErrorHandlerApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I save this file as loggerhead.wsgi in the checkout of loggerhead.&lt;/p&gt;
&lt;p&gt;Next all you need is a basic apache config and a WSGIAlias directive pointing at the wsgi file. Obviously it goes without saying this example is just for illustrative purposes.&lt;/p&gt;
&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="nt"&gt;&amp;lt;VirtualHost&lt;/span&gt; &lt;span class="s"&gt;*:80&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nb"&gt;ServerName&lt;/span&gt; loggerhead

    &lt;span class="nb"&gt;WSGIScriptAlias&lt;/span&gt; / &lt;span class="sx"&gt;/PATH_TO_LOGGERHEAD/loggerhead.wsgi&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;Directory&lt;/span&gt; &lt;span class="s"&gt;/PATH_TO_LOGGERHEAD&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nb"&gt;Order&lt;/span&gt; allow,deny
        &lt;span class="nb"&gt;Allow&lt;/span&gt; from &lt;span class="k"&gt;all&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/Directory&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/VirtualHost&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="note"&gt;
&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;
&lt;p class="last"&gt;The following assumes you have a dns entry for whatever value you give ServerName - In my example I use loggerhead which I have set-up on my local machine to point to 127.0.0.1 so I have a local loggerhead running to view my checkouts.&lt;/p&gt;
&lt;/div&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Change the values of the paths and the ServerName as necessary&lt;/li&gt;
&lt;li&gt;Save this file as loggerhead (or whatever you want to call it) in /etc/apache2/sites-available&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then all you need to do is enable it with&lt;/p&gt;
&lt;div class="syntax"&gt;&lt;pre&gt;sudo a2ensite loggerhead
sudo /etc/init.d/apache2 force-reload
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That's it!&lt;/p&gt;
&lt;p&gt;You can view our code repository at &lt;a href="http://code.projectfondue.com/" class="reference external"&gt;http://code.projectfondue.com/&lt;/a&gt; and a branch for these files is here: &lt;a href="http://code.projectfondue.com/loggerhead-wsgi/trunk/files" class="reference external"&gt;http://code.projectfondue.com/loggerhead-wsgi/trunk/files&lt;/a&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/projectfondue/posts/~4/UOF8O7gmIR8" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.projectfondue.com/2009/11/26/loggerhead-and-mod-wsgi</feedburner:origLink></entry>
  <entry xml:base="http://blog.projectfondue.com/feed.atom">
    <title type="text">Python script for Text Link Ads</title>
    <id>tag:blog.projectfondue.com,2009-10-01:/entry;2009/10/1/python-script-for-text-link-ads</id>
    <updated>2009-11-04T15:25:28Z</updated>
    <published>2009-10-01T18:31:00Z</published>
    <link href="http://feedproxy.google.com/~r/projectfondue/posts/~3/pgAJuqaHBl0/python-script-for-text-link-ads" />
    <author>
      <name>Ed Eliot</name>
    </author>
    <content type="html">&lt;p&gt;To counter this I've written a simple Python script which replicates the functionality of their PHP script. It should be pretty solid and we've been using it on one of our sites for a while but, as this is the first bit of proper Python I've written, please go easy on me if you spot mistakes!&lt;/p&gt;
&lt;div id="usage" class="section"&gt;
&lt;h2&gt;Usage&lt;/h2&gt;
&lt;p&gt;The script is pretty easy to use. Start by including the library.&lt;/p&gt;
&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;tla&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The quickest way to test out the library is probably with the python command line interpreter. This will allow you to introspect its properties and methods with out initially worrying about how to make it sit alongside your own code.&lt;/p&gt;
&lt;p&gt;Next create an instance of the TLA class passing the inventory code that was supplied to you by TLA.&lt;/p&gt;
&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="n"&gt;tla&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TextLinkAds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'ENTER_TLA_INVENTORY_KEY_HERE'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The class has methods to supply the raw data or that same data formatted as an HTML unordered list.&lt;/p&gt;
&lt;div class="syntax"&gt;&lt;pre&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tla&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;tla&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_html&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you're using a templating engine such as &lt;a href="http://jinja.pocoo.org/2/" class="reference external"&gt;jinja2&lt;/a&gt; you'll probably need to make sure you mark the TLA output as "safe" to prevent to the engine from escaping the HTML tags returned.&lt;/p&gt;
&lt;/div&gt;
&lt;div id="requirements" class="section"&gt;
&lt;h2&gt;Requirements&lt;/h2&gt;
&lt;p&gt;The script uses a couple of external libraries - &lt;a href="http://code.google.com/p/httplib2/" class="reference external"&gt;httplib2&lt;/a&gt; and &lt;a href="http://www.tummy.com/Community/software/python-memcached/" class="reference external"&gt;memcache&lt;/a&gt; - httplib2 is required but memcache is optional and is, by default, disabled.&lt;/p&gt;
&lt;p&gt;You can install both libraries with the following:&lt;/p&gt;
&lt;div class="syntax"&gt;&lt;pre&gt;sudo easy_install python-memcached httplib2
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The script also write temporary files to a directory specified within the script (by default /tmp). You'll need to make sure that it has permissions to write to this directory or change it to one it can write to.&lt;/p&gt;
&lt;/div&gt;
&lt;div id="source-code" class="section"&gt;
&lt;h2&gt;Source Code&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://code.projectfondue.com/tla/" class="reference external"&gt;The source code for the library is available from our public bazaar repository&lt;/a&gt;. &lt;a href="http://blog.projectfondue.com/downloads/tla-0-1.zip" class="reference external"&gt;You can also download a zip containing all files&lt;/a&gt; and we'll be adding it to PyPi shortly.&lt;/p&gt;
&lt;/div&gt;
&lt;div id="unit-tests" class="section"&gt;
&lt;h2&gt;Unit Tests&lt;/h2&gt;
&lt;p&gt;Stuart's written a number of unit tests for the library. Test coverage currently stands at around 70% which is pretty good. We'll obviously be looking to expand this coverage in due course.&lt;/p&gt;
&lt;/div&gt;
&lt;div id="learning-python" class="section"&gt;
&lt;h2&gt;Learning Python&lt;/h2&gt;
&lt;p&gt;Being new to Python, I learned quite a lot whilst writing the script. Stuart and Cyril provided plenty of suggestions which resulted in a number of rewrites. Much of this feedback was gathered via a lengthy code review, managed with Google's excellent code review tool - &lt;a href="http://code.google.com/appengine/articles/rietveld.html" class="reference external"&gt;rietveld&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here's a few nuggets of information you might find useful, if like me, you're just starting out.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;httplib2 is much better than urllib2. It does far more out of box resulting in shorter, cleaner code.&lt;/li&gt;
&lt;li&gt;Python provides excellent facilities for logging information - be it to a text file, by email or over HTTP. I found it a little confusing initially but perseverance definitely pays off. The &lt;a href="http://docs.python.org/library/logging.html" class="reference external"&gt;Python docs&lt;/a&gt; have detailed information about what's possible and of course my script demonstrates relatively simple but effective usage.&lt;/li&gt;
&lt;li&gt;Python uses Exceptions for every type of error. This may seem a little strange if you're used to PHPs rather hectic approach to handling errors. You'll need to get used to using try..except blocks everywhere in Python. Also, be careful to be explicit about what errors your catching. Naked excepts (those that catch every conceivable error) make it harder to track down problems later.&lt;/li&gt;
&lt;li&gt;Building up a string by appending to a list which you later join is a common idiom in Python. As strings are immutable, concatenation results in a copy of the string being created every time.&lt;/li&gt;
&lt;li&gt;Python supports calling functions and methods with named parameters as well as **kwargs - a dictionary from which named function parameters can be retrieved without the need for them to form part of the actual function definition. I wish PHP supported similar functionality.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/projectfondue/posts/~4/pgAJuqaHBl0" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.projectfondue.com/2009/10/1/python-script-for-text-link-ads</feedburner:origLink></entry>
  <entry xml:base="http://blog.projectfondue.com/feed.atom">
    <title type="text">Google Chrome Frame — good or bad for the web?</title>
    <id>tag:blog.projectfondue.com,2009-09-23:/entry;2009/9/23/google-chrome-frame-ndash%3B-good-or-bad-for-the-web</id>
    <updated>2009-10-02T20:35:38Z</updated>
    <published>2009-09-23T13:05:00Z</published>
    <link href="http://feedproxy.google.com/~r/projectfondue/posts/~3/_2hTiJZS8NQ/google-chrome-frame-good-or-bad-for-the-web" />
    <author>
      <name>Stuart Colville</name>
    </author>
    <content type="html">&lt;p&gt;Here is Google's description of what Chrome Frame is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Google Chrome Frame is an early-stage open source plug-in that seamlessly brings Google Chrome's open web technologies and speedy JavaScript engine to Internet Explorer. With Google Chrome Frame, you can:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Start using open web technologies - like the HTML5 canvas tag - right away, even technologies that aren't yet supported in Internet Explorer 6, 7, or 8.&lt;/li&gt;
&lt;li&gt;Take advantage of JavaScript performance improvements to make your apps faster and more responsive.&lt;/li&gt;
&lt;/ul&gt;
&lt;p class="attribution"&gt;—&lt;a href="http://code.google.com/chrome/chromeframe/" class="reference external"&gt;http://code.google.com/chrome/chromeframe/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I'm intrigued by &lt;a href="http://code.google.com/chrome/chromeframe/" class="reference external"&gt;Google Frame&lt;/a&gt;; on one hand it's a pretty neat way of providing a more advanced experience to users of Internet Explorer, but I'm also concerned that it's providing a prop to browsers that really should be moving towards deprecation. If a browser isn't capable of displaying a site wouldn't it make more sense to point people in the direction of browsers that are more advanced?&lt;/p&gt;
&lt;p&gt;Is this also saying that Google Wave will need Chrome Frame because it will only be meaningful to users with the most up to date technology. If you aren't up to date is there no base-line experience? If that's the case, a future that ignores progressive enhancement has a nasty aroma to it.&lt;/p&gt;
&lt;div class="admonition-update-24th-september-2009 admonition"&gt;
&lt;p class="first admonition-title"&gt;Update: 24th September 2009&lt;/p&gt;
&lt;p class="last"&gt;&lt;a href="http://googlewavedev.blogspot.com/2009/09/google-wave-in-internet-explorer.html" class="reference external"&gt;According to this post on the Google Wave Blog&lt;/a&gt;, it seems IE 6,7 and 8 users will not be able to use Google Wave unless they install the Google Frame Plugin.&lt;/p&gt;
&lt;/div&gt;
&lt;div id="google-frame-and-accessibility" class="section"&gt;
&lt;h2&gt;Google Frame and Accessibility&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://www.paciellogroup.com/blog/?p=444" class="reference external"&gt;Early investigations by Steve Faulkner&lt;/a&gt; have shown that the inclusion of Google Frame locks out users of assisitive technologies completely.&lt;/p&gt;
&lt;p&gt;Clearly this is an early release and assistive technology support could be improved in a future release. Whilst I'm happy to be proved wrong, I somehow doubt this will change given the epic technical challenges involved. That said, if anyone can do it, Google is a company that is best placed to make it happen.&lt;/p&gt;
&lt;div id="elsewhere" class="section"&gt;
&lt;h3&gt;Elsewhere&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a href="http://arstechnica.com/microsoft/news/2009/09/microsoft-google-chrome-frame-makes-ie-less-secure.ars" class="reference external"&gt;A Microsoft Spokesperson says Google Chrome Frame makes IE less secure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jimray.tumblr.com/post/194793633/more-technical-details-about-google-chrome-frame" class="reference external"&gt;More technical details about Google Chrome Frame&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://groups.google.com/group/google-chrome-frame/browse_thread/thread/7d94aff736a42d29/b3f63eb21c983fd9?hl=en&amp;amp;#b3f63eb21c983fd9" class="reference external"&gt;Google Groups thread with further comment on the acessibility issues&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/projectfondue/posts/~4/_2hTiJZS8NQ" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.projectfondue.com/2009/9/23/google-chrome-frame-good-or-bad-for-the-web</feedburner:origLink></entry>
  <entry xml:base="http://blog.projectfondue.com/feed.atom">
    <title type="text">Apache: Moving from prefork to worker</title>
    <id>tag:blog.projectfondue.com,2009-08-25:/entry;2009/8/25/apache:-moving-from-prefork-to-worker</id>
    <updated>2009-08-26T12:59:58Z</updated>
    <published>2009-08-25T23:53:00Z</published>
    <link href="http://feedproxy.google.com/~r/projectfondue/posts/~3/YEpFdopRQSQ/apache-moving-from-prefork-to-worker" />
    <author>
      <name>Stuart Colville</name>
    </author>
    <content type="html">&lt;div id="differences-between-mpm-versions" class="section"&gt;
&lt;h2&gt;Differences between MPM Versions&lt;/h2&gt;
&lt;p&gt;So what are the differences between Apache MPM ("multi-processing module") types?&lt;/p&gt;
&lt;p&gt;MPM Prefork doesn't use threads and instead spawns child processes to serve requests. MPM Worker on the other hand uses multi-threaded processes where each child process utilises a number of threads:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;By using threads to serve requests, it is able to serve a large number of requests with less system resources than a process-based server. Yet it retains much of the stability of a process-based server by keeping multiple processes available, each with many threads.&lt;/p&gt;
&lt;p class="attribution"&gt;—Apache 2 Documentation&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Something to bear in mind is that you probably won't want to switch to worker if you are using PHP unless you are ok with using PHP as FastCGI and even then the &lt;a href="http://www.php.net/manual/en/faq.installation.php#faq.installation.apache2" class="reference external"&gt;PHP manual doesn't recommend using MPM worker.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For us that means we are now running our PHP apps using prefork and mod_php on a box dedicated to running PHP. This is better in a lot of ways because it means we can tune Apache for each specific application rather than running a mixture of PHP and Python apps on the same hardware.&lt;/p&gt;
&lt;/div&gt;
&lt;div id="converting-to-mpm-worker" class="section"&gt;
&lt;h2&gt;Converting to mpm-worker&lt;/h2&gt;
&lt;p&gt;Actually carrying out the conversion on an Ubuntu box is as simple as running&lt;/p&gt;
&lt;div class="syntax"&gt;&lt;pre&gt;sudo apt-get install apache2-mpm-worker
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That will remove prefork if you have it installed and will install worker in its place and trigger a restart. That's all there is to it. (Though of course YMMV)&lt;/p&gt;
&lt;/div&gt;
&lt;div id="what-difference-does-it-make" class="section"&gt;
&lt;h2&gt;What Difference does it make?&lt;/h2&gt;
&lt;p&gt;In our case used memory levels dropped a reasonable amount as you can see in the last 6th of this graph:&lt;/p&gt;
&lt;img src="/images/radha.png" alt="Graph Showing memory usage down when switched to MPM worker"&gt;
&lt;div id="related-reading" class="section"&gt;
&lt;h3&gt;Related Reading&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a href="http://lucumr.pocoo.org/2007/9/30/pushing-apache-performance" class="reference external"&gt;Pushing Apache Performance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://httpd.apache.org/docs/2.2/mpm.html" class="reference external"&gt;Multi-Processing Modules (MPMs)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/projectfondue/posts/~4/YEpFdopRQSQ" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.projectfondue.com/2009/8/25/apache-moving-from-prefork-to-worker</feedburner:origLink></entry>
  <entry xml:base="http://blog.projectfondue.com/feed.atom">
    <title type="text">CSS Sprite Generator v4.0 available on Launchpad</title>
    <id>tag:blog.projectfondue.com,2009-08-05:/entry;2009/8/5/version-4-of-source-code-for-css-sprite-generator-available-in-launchpad</id>
    <updated>2009-09-01T11:03:28Z</updated>
    <published>2009-08-05T19:25:00Z</published>
    <link href="http://feedproxy.google.com/~r/projectfondue/posts/~3/iMcIjvX2i3E/version-4-of-source-code-for-css-sprite-generator-available-in-launchpad" />
    <author>
      <name>Ed Eliot</name>
    </author>
    <content type="html">&lt;p&gt;This is useful for sprites which contain gradients that need to be repeated in a specific direction. There's also been some suggestion, particularly from the Yahoo! performance guys, that &lt;a href="http://developer.yahoo.com/performance/rules.html#opt_sprites" class="reference external"&gt;building sprites horizontally results in a smaller overall image size&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Arranging the images in the sprite horizontally as opposed to vertically usually results in a smaller file size.&lt;/p&gt;
&lt;p class="attribution"&gt;—Yahoo! Exceptional Performance Team&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div id="other-changes" class="section"&gt;
&lt;h2&gt;Other Changes&lt;/h2&gt;
&lt;div id="generated-css" class="section"&gt;
&lt;h3&gt;Generated CSS&lt;/h3&gt;
&lt;p&gt;Displaying the generated CSS within a textarea field (rather than a scrolling div) to enable select all and easier copy and paste.&lt;/p&gt;
&lt;/div&gt;
&lt;div id="component-spacing" class="section"&gt;
&lt;h3&gt;Component Spacing&lt;/h3&gt;
&lt;p&gt;A reduction in the default spacing (horizontal and vertical) between component images in the sprite. This makes the tool kinder to our servers and means, with a default generation, the browser has to handle a smaller uncompressed image in memory. &lt;a href="http://developer.yahoo.com/performance/rules.html#opt_sprites" class="reference external"&gt;This should be of particular benefit to the iphone which doesn't seem to handle large sprites too well.&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;"Be mobile-friendly" and don't leave big gaps between the images in a sprite. This doesn't affect the file size as much but requires less memory for the user agent to decompress the image into a pixel map. 100x100 image is 10 thousand pixels, where 1000x1000 is 1 million pixels&lt;/p&gt;
&lt;p class="attribution"&gt;—Yahoo! Exceptional Performance Team&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There's a balance to be had here, of course. The usual reason for including space between component images is to allow for text sizes increases which would otherwise result in partial display of the next image in the sprite. You can see how this would be a particular problem on something like the navigation of the &lt;a href="http://www.yahoo.com/" class="reference external"&gt;Yahoo! home page&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div id="language-selection" class="section"&gt;
&lt;h3&gt;Language Selection&lt;/h3&gt;
&lt;p&gt;Conversion of the language selection interface from a drop down box to a list of links to make it easier for someone to switch to their native language, particularly where they don't understand the currently displayed language. There's an &lt;a href="http://www.w3.org/International/questions/qa-navigation-select" class="reference external"&gt;interesting analysis of the use of drop downs versus links&lt;/a&gt; in the W3C i18n FAQ with the relative benefits and pitfalls of each approach.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="looking-forward" class="section"&gt;
&lt;h2&gt;Looking Forward&lt;/h2&gt;
&lt;p&gt;We've got a few other bugs that need fixing. We'll be working on those shortly and, in due course, we'll also be developing a command line version of the tool. This should make it easy to incorporate into an automated build script. Check back regularly for further details and do drop us a line if you've got any suggestions.&lt;/p&gt;
&lt;/div&gt;
&lt;div id="get-the-code" class="section"&gt;
&lt;h2&gt;Get the Code&lt;/h2&gt;
&lt;p&gt;You can &lt;a href="https://launchpad.net/css-sprite-generator" class="reference external"&gt;get the source code here on Launchpad&lt;/a&gt;. As always comments, suggestions, bugs and patches are welcomed.&lt;/p&gt;
&lt;/div&gt;
&lt;div id="try-version-4-online" class="section"&gt;
&lt;h2&gt;Try Version 4 Online&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://spritegen.website-performance.org/" class="reference external"&gt;CSS Sprite Generator version 4&lt;/a&gt; is available online where you can dive right in and try out the latest features.&lt;/p&gt;
&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/projectfondue/posts/~4/iMcIjvX2i3E" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.projectfondue.com/2009/8/5/version-4-of-source-code-for-css-sprite-generator-available-in-launchpad</feedburner:origLink></entry>
  <entry xml:base="http://blog.projectfondue.com/feed.atom">
    <title type="text">Raclette: Web App Utils for Python</title>
    <id>tag:blog.projectfondue.com,2009-06-28:/entry;2009/6/28/raclette:-web-app-utils-for-python</id>
    <updated>2009-07-14T10:58:36Z</updated>
    <published>2009-07-12T12:00:00Z</published>
    <link href="http://feedproxy.google.com/~r/projectfondue/posts/~3/qxuY7nPiE1w/raclette:-web-app-utils-for-python" />
    <author>
      <name>Stuart Colville</name>
    </author>
    <content type="html">&lt;p&gt;The goals for Raclette are to provide well tested middlewares and libraries that can be used to facilitate web development. We're also looking to keep the quality of code at a high standard as much as possible whilst balancing that with getting code out there so developers can try it out and provide feedback.&lt;/p&gt;
&lt;div id="raclette-gbs-graded-browser-support-middleware" class="section"&gt;
&lt;h2&gt;raclette.gbs: Graded Browser Support Middleware&lt;/h2&gt;
&lt;p&gt;The first app off the blocks is a WSGI middleware which provides a solution to implementing Yahoo's Graded Browser support strategy see &lt;a href="http://developer.yahoo.com/yui/articles/gbs/" class="reference external"&gt;http://developer.yahoo.com/yui/articles/gbs/&lt;/a&gt; for more information.&lt;/p&gt;
&lt;div id="installation" class="section"&gt;
&lt;h3&gt;Installation&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;sudo easy_install raclette.gbs
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To use the middleware simply wrap the init of the middleware around your WSGI application&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;raclette.gbs&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="n"&gt;GradedBrowser&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;application&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GradedBrowser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;raclette.gbs works by analyzing the user-agent string and returning a grade stating that the browser is C, A or X grade. Yahoo's own strategy only provides details of which browser's are A grade so the C grade matrix is pretty much created based on guess-work around the notion that C-Grade browsers should be Antiquated and rare.&lt;/p&gt;
&lt;p&gt;Ultimately for the purposes of this middleware only C-grade browsers really need to be identified as A and X grade are generally treated the same. However to be able to give the end user more scope to do different things with browser grades in development or production C and A grades are explicitly identified. It's up to the user to modify the browser matrix should they wish to add or drop support for any particular browser.&lt;/p&gt;
&lt;/div&gt;
&lt;div id="known-issues" class="section"&gt;
&lt;h3&gt;Known Issues&lt;/h3&gt;
&lt;p&gt;There's clearly some work to be done in terms of extending the data used to provide the decisions on which browsers are and aren't supported. With that in mind we're happy to get feedback on which browsers you think need to be indentified. Clearly it doesn't have to be something that's in Yahoo's matrix of support as it's clear that anyone using this may wish to define their own matrix of support.&lt;/p&gt;
&lt;p&gt;Caching is not currently implemented. As the UA string is parsed on every request it's fairly crucial that caching is added - expect several caching solutions to be made available in subsequent releases.&lt;/p&gt;
&lt;/div&gt;
&lt;div id="future-possibilities" class="section"&gt;
&lt;h3&gt;Future Possibilities&lt;/h3&gt;
&lt;p&gt;Something that came up early on was an idea around extending support to include some notion of graded mobile browser support in the sense that you might have MA, MX and MC. At this point it's not clear if having any separate grades for mobile devices is a good thing or not, but certainly being able to detect common mobile browsers would be useful.&lt;/p&gt;
&lt;/div&gt;
&lt;div id="getting-the-code" class="section"&gt;
&lt;h3&gt;Getting the code&lt;/h3&gt;
&lt;p&gt;The code is available on launchpad.net at &lt;a href="https://launchpad.net/raclette.gbs" class="reference external"&gt;https://launchpad.net/raclette.gbs&lt;/a&gt; -- Contributions and patches gratefully received. All code is licensed under the modified BSD license.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/projectfondue/posts/~4/qxuY7nPiE1w" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.projectfondue.com/2009/6/28/raclette:-web-app-utils-for-python</feedburner:origLink></entry>
  <entry xml:base="http://blog.projectfondue.com/feed.atom">
    <title type="text">Welcome!</title>
    <id>tag:blog.projectfondue.com,2009-06-27:/entry;2009/6/27/welcome-to-the-project-fondue-blog</id>
    <updated>2009-07-12T10:48:31Z</updated>
    <published>2009-07-12T10:44:00Z</published>
    <link href="http://feedproxy.google.com/~r/projectfondue/posts/~3/WBz9oA_KuIg/welcome" />
    <author>
      <name>Stuart Colville</name>
    </author>
    <content type="html">&lt;p&gt;We've been hanging out in Paris for the weekend for a mini sprint/planning session. Naturally we made a point of getting out for Fondue which as always was pretty awesome.&lt;/p&gt;
&lt;p&gt;One of the things we've been up to is spending some time bugfixing and putting out the v3.0 release of &lt;a href="http://spritegen.website-performance.org/" class="reference external"&gt;CSS Sprite Generator&lt;/a&gt; which Ed's been working on recently. Ed's added a feature for Vertical and Horizontal layout of sprites which has been requested a few times. Translations are now available via dedicated subdomains which is a distinct improvement. In addition a Russian Translation contributed by Pavel Sorokin and a Turkish Translation provided by Kerem Can Caliskan are now live.&lt;/p&gt;
&lt;p&gt;The time in Paris gave us a time to finalise this blog and we've also planned out future changes to our architecture and systems which has been invaluable to help keep everything running smoothly whilst minimising all manual repetitive tasks to next to nothing.&lt;/p&gt;
&lt;p&gt;We'll have plenty to talk about in the future; from the details on development of existing applications, as well as exciting things that are coming up. Most importantly for us is that this can be a two-way conversation and we look forward to hearing your thoughts, comments and suggestions on everything at Project Fondue.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/projectfondue/posts/~4/WBz9oA_KuIg" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.projectfondue.com/2009/6/27/welcome</feedburner:origLink></entry>
</feed>
