<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
    xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:wfw="http://wellformedweb.org/CommentAPI/"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:atom="http://www.w3.org/2005/Atom"
    xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
    xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
>
    <channel>
        <title>Silas Sewell - Python</title>
        <atom:link href="http://www.silassewell.com/blog/tag/python/rss2.xml" rel="self" type="application/rss+xml" />
        <link>http://www.silassewell.com/blog/tag/python</link>
        <description>Infrastructure Development</description>
        <lastBuildDate>Sat, 08 Jan 2011 00:00:00 GMT</lastBuildDate>
        <generator>http://www.silassewell.com/</generator>
        <language>en</language>
        <sy:updatePeriod>hourly</sy:updatePeriod>
        <sy:updateFrequency>1</sy:updateFrequency>

        <item>
            <title>txsrv: Message-based Twisted Services</title>
            <link>http://www.silassewell.com/blog/2010/09/12/txsrv-message-based-twisted-services/</link>
            <pubDate>Sun, 12 Sep 2010 00:00:00 GMT</pubDate>
            <dc:creator>silas</dc:creator>
            <category><![CDATA[AMQP]]></category><category><![CDATA[Fedora]]></category><category><![CDATA[Python]]></category><category><![CDATA[Twisted]]></category><category><![CDATA[txsrv]]></category>
            <guid isPermaLink="true">http://www.silassewell.com/blog/2010/09/12/txsrv-message-based-twisted-services/</guid>
            <description><![CDATA[<p>I've started work on <a href="http://github.com/silas/txsrv" title="txsrv">txsrv</a>, a Python library that aims to make
developing message-based services in Twisted easy.</p>

<p>The code is still pretty rough, but might be of interest to someone hacking on
AMQP-based Twisted services.</p>

<p>Sample Usage</p>

<ol>
<li><p>Create a new service and change to the project directory.</p>

<pre><code class="prettyprint">$ txsrv create mytest
$ cd mytest
</code></pre></li>
<li><p>Edit the <code class="prettyprint">mytest.conf</code> file so that the <code class="prettyprint">spec_file</code> option is valid.</p>

<pre><code class="prettyprint">[connection:amqp]
type = amqp
host = localhost
port = 5672
vhost = /
user = guest
password = guest
spec_file = /usr/share/amqp/amqp.0-8.xml

[handler:hello]
connection = amqp
exchange = hello
routing_key = default
</code></pre></li>
<li><p>Edit the <code class="prettyprint">mytest.py</code> file so that it prints the message body twice.</p>

<pre><code class="prettyprint">import txsrv

class Service(txsrv.Service):
    @txsrv.handler('hello')
    def hello(self, message):
        print message.body * 2

class ServiceMaker(txsrv.ServiceMaker):
    tapname = 'mytest'
    description = 'A mytest txsrv example.'
    service_type = Service
</code></pre></li>
<li><p>Start the <code class="prettyprint">mytest</code> service and send a message to the <code class="prettyprint">hello</code> exchange.</p>

<pre><code class="prettyprint">$ twistd -n mytest -c mytest.conf
2010-09-12 00:41:10-0400 [-] Log opened.
2010-09-12 00:41:10-0400 [-] twistd 10.1.0 (/usr/bin/python 2.6.4) starting up.
2010-09-12 00:41:10-0400 [-] reactor class: twisted.internet.selectreactor.SelectReactor.
2010-09-12 00:41:10-0400 [-] Starting factory &lt;txsrv.protocol.amqp.AmqpFactory instance at 0x2cce950&gt;
2010-09-12 00:41:10-0400 [AmqpProtocol,client] hellohello
</code></pre></li>
</ol>]]></description>
        </item>

        <item>
            <title>Auto-reload node.js (OS X)</title>
            <link>http://www.silassewell.com/blog/2010/05/16/auto-reload-node-js-os-x/</link>
            <pubDate>Sun, 16 May 2010 00:00:00 GMT</pubDate>
            <dc:creator>silas</dc:creator>
            <category><![CDATA[JavaScript]]></category><category><![CDATA[node.js]]></category><category><![CDATA[Python]]></category><category><![CDATA[restarter]]></category>
            <guid isPermaLink="true">http://www.silassewell.com/blog/2010/05/16/auto-reload-node-js-os-x/</guid>
            <description><![CDATA[<p><a href="http://github.com/silas/restarter" title="restarter">restarter</a> is a simple Python application which runs a specified
command and restarts the command each time a file event occurs in a specified
directory.</p>

<p>I created restarter because there isn't auto-reload functionality built into
<a href="http://nodejs.org/" title="node.js">node.js</a> (at the time of this post).</p>

<p><strong>Example</strong></p>

<pre><code class="prettyprint">[silas@blackbox keyfu.js]$ restarter node keyfu.js
Express started at http://localhost:3000/ in development mode
</code></pre>

<p><strong>Usage</strong></p>

<pre><code class="prettyprint">Usage: restarter [options] command

Options:
  -h, --help     show this help message and exit
  --path=PATH    directory to watch for file event changes
  --ignore=PATH  specifies events to ignore
</code></pre>]]></description>
        </item>

        <item>
            <title>Jinja2 Markdown Extension</title>
            <link>http://www.silassewell.com/blog/2010/05/10/jinja2-markdown-extension/</link>
            <pubDate>Mon, 10 May 2010 00:00:00 GMT</pubDate>
            <dc:creator>silas</dc:creator>
            <category><![CDATA[Jinja2]]></category><category><![CDATA[Markdown]]></category><category><![CDATA[Python]]></category>
            <guid isPermaLink="true">http://www.silassewell.com/blog/2010/05/10/jinja2-markdown-extension/</guid>
            <description><![CDATA[<p>Below is an example of a Markdown extension for <a href="http://jinja.pocoo.org/2/documentation/" title="Jinja2">Jinja2</a>.</p>

<pre><code class="prettyprint">import jinja2
import jinja2.ext
import markdown2

class Markdown2Extension(jinja2.ext.Extension):
    tags = set(['markdown2'])

    def __init__(self, environment):
        super(Markdown2Extension, self).__init__(environment)
        environment.extend(
            markdowner=markdown2.Markdown()
        )   

    def parse(self, parser):
        lineno = parser.stream.next().lineno
        body = parser.parse_statements(
            ['name:endmarkdown2'],
            drop_needle=True
        )
        return jinja2.nodes.CallBlock(
            self.call_method('_markdown_support'),
            [],
            [],
            body
        ).set_lineno(lineno)

    def _markdown_support(self, caller):
        return self.environment.markdowner.convert(caller()).strip()

env = jinja2.Environment(extensions=[Markdown2Extension])

text = """ 
{% markdown2 %}
Hello World
===========

 1. One
 2. {{ two }}
 3. Three
{% endmarkdown2 %}
"""

html = env.from_string(text).render(two='Two')

print html
</code></pre>

<p>Which would result in the following output:</p>

<pre><code class="prettyprint">&lt;h1&gt;Hello World&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;One&lt;/li&gt;
&lt;li&gt;Two&lt;/li&gt;
&lt;li&gt;Three&lt;/li&gt;
&lt;/ol&gt;
</code></pre>]]></description>
        </item>

        <item>
            <title>Google App Engine Middleware (gaem)</title>
            <link>http://www.silassewell.com/blog/2009/12/29/google-app-engine-middleware-gaem/</link>
            <pubDate>Tue, 29 Dec 2009 00:00:00 GMT</pubDate>
            <dc:creator>silas</dc:creator>
            <category><![CDATA[Fedora]]></category><category><![CDATA[gaem]]></category><category><![CDATA[Google]]></category><category><![CDATA[Google App Engine]]></category><category><![CDATA[Projects]]></category><category><![CDATA[Python]]></category><category><![CDATA[Reverse Proxy]]></category><category><![CDATA[Software]]></category>
            <guid isPermaLink="true">http://www.silassewell.com/blog/2009/12/29/google-app-engine-middleware-gaem/</guid>
            <description><![CDATA[<p><a href="http://github.com/silas/gaem" title="Google App Engine Middleware">Google App Engine Middleware</a> (gaem) is a collection of utilities for
hosting external sites on Google App Engine.</p>

<p>I created gaem because I wanted to host my blog on an unreliable server and let
Google App Engine serve the content while my server was down or in maintenance
mode.</p>

<p>The basic design is similar to that of <a href="http://docs.djangoproject.com/en/dev/topics/http/middleware/" title="Django's middleware">Django's middleware</a>. A request
travels through a list of components which can either manipulate the request or
provide a response. The response is filtered back through the components and
served to the requester.</p>

<p>A basic implementation looks something like</p>

<pre><code class="prettyprint">import gaem
import gaem.middleware
import gaem.middleware.cache
import gaem.middleware.dos
import gaem.middleware.fetch

URL = 'http://www.example.org'

MIDDLEWARE_CLASSES = (
    gaem.middleware.cache.Memcache(),
    gaem.middleware.cache.Datastore(),
    gaem.middleware.dos.DoS(),
    gaem.middleware.fetch.Fetch(url=URL),
)

application = gaem.Application(MIDDLEWARE_CLASSES)

if __name__ == '__main__':
    application.run()
</code></pre>

<p>When a request first hits this application it is handled by the Memcache
component. This basic caching component checks the Google App Engine Memcache
service to see if the page is in the cache. If so it simply returns the cached
response, otherwise the request proceeds to the Datastore component which does
pretty much the same thing except it uses Google Datastore for persistence. If
both caching components fail the the request goes through a DoS protection
component and is finally retrieved from the backend server by the Fetch
component.</p>

<p>Using a setup like this gaem acts as a rudimentary reverse proxy and while most
of the functionality I've implemented thus far is for this type setup, I plan
on adding features not traditionally found in a reverse proxy.</p>

<h3>Current Features</h3>

<ul>
<li><a href="http://github.com/silas/gaem/blob/a9d187f65229796c1e92b479735f215c4f1e7000/gaem/middleware/cache.py" title="Caching">Caching</a></li>
<li><a href="http://github.com/silas/gaem/blob/a9d187f65229796c1e92b479735f215c4f1e7000/gaem/middleware/fetch.py" title="Backend fetch">Backend fetch</a></li>
<li>Gracefully handle a dead backend</li>
<li><a href="http://github.com/silas/gaem/blob/a9d187f65229796c1e92b479735f215c4f1e7000/gaem/middleware/dos.py" title="DoS protection">DoS protection</a></li>
<li><a href="http://github.com/silas/gaem/blob/a9d187f65229796c1e92b479735f215c4f1e7000/gaem/middleware/api.py" title="API for expiring content">API for expiring content</a></li>
</ul>

<h3>Possible Future Features</h3>

<ul>
<li>Initial and periodic crawler (pre-cache and other hooks)</li>
<li>RESTful API for managing content (put, delete, etc...)</li>
<li>Web interface</li>
<li>XSS protection</li>
<li>Some ESI support</li>
</ul>

<p>But what makes gaem really cool for developers is how easy it is to create
custom components.</p>

<p>A basic component looks like</p>

<pre><code class="prettyprint">from gaem import middleware

class DoesNothing(middleware.Base):

    def process_request(self, request):
        return request

    def process_response(self, response, request):
        return response
</code></pre>

<p>A default gaem component should inherit from <code class="prettyprint">gaem.middleware.Base</code> and
implement <code class="prettyprint">process_request</code> and/or <code class="prettyprint">process_response</code>.</p>

<p>The <code class="prettyprint">process_request</code> function lets you either manipulate the request (ex:
strip the "cookie" header) and pass it along or use the request to create and
return a response (ex: do a fetch to the backend server). The
<code class="prettyprint">process_response</code> function lets you filter the response (ex: translate body
into pig latin) and do side affects (ex: store response in memcache) before the
response is sent to the requester.</p>

<p>The Request/Response objects are borrowed from <a href="http://pythonpaste.org/webob/" title="WebOb">WebOb</a> and can be
manipulated using the interfaces defined in the <a href="http://pythonpaste.org/webob/modules/webob.html" title="WebOb documentation">WebOb documentation</a>.</p>

<p>gaem is currently pretty rough and likely to change over the next couple of
months, but if you're a Python hacker I'd love to hear some feedback
(<a href="http://www.silassewell.com/about/contact/" title="Contact Silas Sewell">contact me</a> or <a href="http://github.com/silas/gaem/issues" title="gaem issues">submit an issue</a>).</p>

<p>P.S. You can see the application I created for this site in the <a href="http://github.com/silas/gaem/tree/master/examples/wordpress/" title="gaem WordPress example">examples directory</a>.</p>]]></description>
        </item>

        <item>
            <title>Stomping with Python and ActiveMQ (Stomp Framework)</title>
            <link>http://www.silassewell.com/blog/2009/08/27/stomping-with-python-and-activemq-stomp-framework/</link>
            <pubDate>Thu, 27 Aug 2009 00:00:00 GMT</pubDate>
            <dc:creator>silas</dc:creator>
            <category><![CDATA[ActiveMQ]]></category><category><![CDATA[Fedora]]></category><category><![CDATA[Programming]]></category><category><![CDATA[Projects]]></category><category><![CDATA[Python]]></category><category><![CDATA[python-stomping]]></category><category><![CDATA[STOMP]]></category>
            <guid isPermaLink="true">http://www.silassewell.com/blog/2009/08/27/stomping-with-python-and-activemq-stomp-framework/</guid>
            <description><![CDATA[<p><a href="http://silassewell.googlecode.com/svn/trunk/projects/python-stomping" title="Python Stomping">python-stomping</a> is a simple <a href="http://en.wikipedia.org/wiki/Streaming_Text_Orientated_Messaging_Protocol" title="Stomp">Stomp</a> framework I wrote which makes
creating stomp services in Python easy.</p>

<ol>
<li><p>Install requirements</p>

<pre><code class="prettyprint">$ sudo yum install python-twisted python-stomper
</code></pre></li>
<li><p>Checkout stomping</p>

<pre><code class="prettyprint">$ svn export http://silassewell.googlecode.com/svn/trunk/projects/python-stomping python-stomping
$ cd python-stomping
</code></pre></li>
<li><p>Update the <code class="prettyprint">example.py</code> file to use your <code class="prettyprint">host</code>, <code class="prettyprint">port</code>, <code class="prettyprint">username</code> and
<code class="prettyprint">password</code> ActiveMQ/Stomp broker settings</p>

<pre><code class="prettyprint">from stomping import Stomping, route

class MyStomping(Stomping):

def init(self):
    self.send('/queue/test1', 'init test1')
    self.send('/queue/test2', 'init test2')

@route('/queue/test1')
def a_test(self, message):
    print 'a_test: %s' % message['body']

@route('/queue/test1')
@route('/queue/test2')
def b_test(self, message):
    print 'b_test: %s' % message['body']

if __name__ == '__main__':
    stomp = MyStomping(host='127.0.0.1', port=61613, username='guest', password='guest')
    stomp.run()
</code></pre></li>
<li><p>Run <code class="prettyprint">example.py</code> (Ctrl+c to quit)</p>

<pre><code class="prettyprint">$ python example.py 
a_test: init test1
b_test: init test1
b_test: init test2
</code></pre></li>
</ol>

<p>NOTE: python-stomping is just a light wrapper around Twisted and stomper and is
based on an <a href="http://code.google.com/p/stomper/source/browse/trunk/lib/stomper/examples/sender.py" title="sender example">example</a> provided in the stomper code.</p>]]></description>
        </item>

        <item>
            <title>Python Line-by-line Profiler (line_profiler and kernprof)</title>
            <link>http://www.silassewell.com/blog/2009/05/28/python-line-by-line-profiler-line_profiler-and-kernprof/</link>
            <pubDate>Thu, 28 May 2009 00:00:00 GMT</pubDate>
            <dc:creator>silas</dc:creator>
            <category><![CDATA[Fedora]]></category><category><![CDATA[kernprof]]></category><category><![CDATA[line_profiler]]></category><category><![CDATA[Programming]]></category><category><![CDATA[Python]]></category><category><![CDATA[RPM]]></category>
            <guid isPermaLink="true">http://www.silassewell.com/blog/2009/05/28/python-line-by-line-profiler-line_profiler-and-kernprof/</guid>
            <description><![CDATA[<p>The following is a quick and dirty guide to getting started with
<a href="http://packages.python.org/line_profiler/" title="line profiler">line_profiler</a>, a Python line-by-line profiler, on Fedora.</p>

<ol>
<li><a href="http://code.google.com/p/silassewell/wiki/PackagingRPMs" title="Packaging RPMS">Build</a> and install the <a href="http://silassewell.googlecode.com/files/python-line_profiler-1.0-0.1.b2.fc10.src.rpm" title="line profiler SRPM">python-line_profiler</a> package</li>
<li><p>Create a file called <code class="prettyprint">test.py</code> with the code below</p>

<pre><code class="prettyprint">import random, time

def sleep():
    seconds = random.randint(0, 5)
    print 'Sleeping %s seconds' % seconds
    time.sleep(seconds)

@profile
def test():
    sleep()
    sleep()
    sleep()

test()
</code></pre></li>
<li><p>Profile <code class="prettyprint">test.py</code></p>

<pre><code class="prettyprint">[silas@silas ~]$ kernprof.py -l test.py
Sleeping 4 seconds
Sleeping 5 seconds
Sleeping 2 seconds
Wrote profile results to test.py.lprof
</code></pre></li>
<li><p>View the results</p>

<pre><code class="prettyprint">[silas@silas ~]$ python -m line_profiler test.py.lprof
Timer unit: 1e-06 s

File: test.py
Function: test at line 8
Total time: 10.9994 s

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
     8                                           @profile
     9                                           def test():
    10         1      3999416 3999416.0     36.4      sleep()
    11         1      4999982 4999982.0     45.5      sleep()
    12         1      1999990 1999990.0     18.2      sleep()
</code></pre></li>
</ol>

<p>NOTE: I have a <a href="https://bugzilla.redhat.com/show_bug.cgi?id=502978" title="Package Review">package review</a> up for line_profiler and it should be
available via yum eventually.</p>]]></description>
        </item>

        <item>
            <title>String Slicing in Bash (like Python)</title>
            <link>http://www.silassewell.com/blog/2009/03/12/string-slicing-in-bash-like-python/</link>
            <pubDate>Thu, 12 Mar 2009 00:00:00 GMT</pubDate>
            <dc:creator>silas</dc:creator>
            <category><![CDATA[Bash]]></category><category><![CDATA[Programming]]></category><category><![CDATA[Python]]></category><category><![CDATA[String]]></category><category><![CDATA[Systems Administration]]></category>
            <guid isPermaLink="true">http://www.silassewell.com/blog/2009/03/12/string-slicing-in-bash-like-python/</guid>
            <description><![CDATA[<p>A simple function to slice strings in Bash similar to Python's string slicing functionality.</p>

<h3>Examples</h3>

<pre><code class="prettyprint">[silas@pluto ~]$ string_slice "12345" 0 1
1
[silas@pluto ~]$ string_slice "12345" 0 3
123
[silas@pluto ~]$ string_slice "12345" 2 3
3
[silas@pluto ~]$ string_slice "12345" 2 -2
3
[silas@pluto ~]$ string_slice "12345" -3
345
</code></pre>

<h3>Implementation</h3>

<pre><code class="prettyprint">function string_slice {
    STRING="$1"
    declare -i LENGTH="${#STRING}"
    declare -i START="$2"
    declare -i END="$3"
    if [ $START -lt 0 ]; then
        START=$[ $LENGTH + $START ]
    fi
    if [ $END -le 0 ]; then
        END=$[ $LENGTH + $END ]
    fi
    START=$[ $START + 1 ]
    (echo "$STRING" | cut -c $START-$END) 2&gt; /dev/null
}
</code></pre>]]></description>
        </item>

        <item>
            <title>Introducing the FuncShell</title>
            <link>http://www.silassewell.com/blog/2009/01/30/introducing-the-func-shell/</link>
            <pubDate>Fri, 30 Jan 2009 00:00:00 GMT</pubDate>
            <dc:creator>silas</dc:creator>
            <category><![CDATA[Func]]></category><category><![CDATA[Func Shell]]></category><category><![CDATA[FuncShell]]></category><category><![CDATA[Projects]]></category><category><![CDATA[Python]]></category><category><![CDATA[Systems Administration]]></category>
            <guid isPermaLink="true">http://www.silassewell.com/blog/2009/01/30/introducing-the-func-shell/</guid>
            <description><![CDATA[<p><strong>Update</strong>: I am currently refactoring FuncShell; please use the following
code: <a href="http://github.com/silas/funcshell/raw/f630b9dd552287f5fe4b3f46ca09442499c68f0f/src/shell.py" title="shell.py">shell.py</a>.</p>

<p>I created <a href="http://github.com/silas/funcshell" title="funcshell">funcshell</a> for running <a href="https://fedorahosted.org/func/" title="func">Func</a> modules in a more
intuitive manner.</p>

<p>The current implementation only supports the command module, but more will be
released shortly.</p>

<p><strong>Code:</strong> <a href="http://github.com/silas/funcshell" title="funcshell">http://github.com/silas/funcshell</a></p>

<h3>Example Usage</h3>

<pre><code class="prettyprint">[root@pluto ~]# python shell.py
fs&gt; use web*.example.org
fs&gt; get hosts
web01.example.org
web02.example.org
fs&gt; !du -sh /tmp
================================================================================
== web02.example.org                                                          ==
================================================================================

236K    /tmp

================================================================================
== web01.example.org                                                          ==
================================================================================

217M    /tmp

fs&gt; !cat /proc/meminfo | grep MemTotal | awk '{ print $2 }'
================================================================================
== web02.example.org                                                          ==
================================================================================

1027116

================================================================================
== web01.example.org                                                          ==
================================================================================

1027116

fs&gt; exit
[root@pluto ~]#
</code></pre>]]></description>
        </item>

        <item>
            <title>IPython + Python: Single Bash Command</title>
            <link>http://www.silassewell.com/blog/2008/12/01/ipython-python-single-bash-command/</link>
            <pubDate>Mon, 01 Dec 2008 00:00:00 GMT</pubDate>
            <dc:creator>silas</dc:creator>
            <category><![CDATA[Bash]]></category><category><![CDATA[IPython]]></category><category><![CDATA[Python]]></category><category><![CDATA[Systems Administration]]></category>
            <guid isPermaLink="true">http://www.silassewell.com/blog/2008/12/01/ipython-python-single-bash-command/</guid>
            <description><![CDATA[<p>The following is a simple Bash function you can paste into your bashrc file to
start Python/IPython depending on the context.</p>

<h3>~/.bashrc</h3>

<pre><code class="prettyprint">function python {
    IPYTHON="/usr/bin/ipython"
    PYTHON="/usr/bin/python"

    if [[ -n $1 ]]; then
        $PYTHON $@
    elif [[ -e $IPYTHON ]]; then
        $IPYTHON
    else
        $PYTHON
    fi
}
</code></pre>]]></description>
        </item>

        <item>
            <title>Push: Func Module to Run Arbitrary Python Code</title>
            <link>http://www.silassewell.com/blog/2008/11/18/push-func-module-to-run-arbitrary-python-code/</link>
            <pubDate>Tue, 18 Nov 2008 00:00:00 GMT</pubDate>
            <dc:creator>silas</dc:creator>
            <category><![CDATA[Func]]></category><category><![CDATA[Programming]]></category><category><![CDATA[Python]]></category><category><![CDATA[Systems Administration]]></category>
            <guid isPermaLink="true">http://www.silassewell.com/blog/2008/11/18/push-func-module-to-run-arbitrary-python-code/</guid>
            <description><![CDATA[<p><a href="https://fedorahosted.org/func/" title="Func">Func</a> is a nifty, although not yet polished, Python-based service for
running tasks on many hosts at once. It lets you do things like restart
<a href="https://fedorahosted.org/func/wiki/ServiceModule" title="Service Module">Apache instances</a>, <a href="https://fedorahosted.org/func/wiki/YumModule" title="Yum Module">run yum updates</a> or
<a href="https://fedorahosted.org/func/wiki/VirtModule" title="Virt Module">provision virtual machines</a>.</p>

<p>You can accomplish theses tasks via the command line interface</p>

<pre><code class="prettyprint">func web-*.example.net call service restart httpd
</code></pre>

<p>or through the Python API</p>

<pre><code class="prettyprint">import func.overlord.client as fc

client = fc.Client('web-*.example.net')

print client.service.restart('httpd')
</code></pre>

<p>One of the annoying issues I'm dealing with right now is the distribution of
Func modules, which for various reasons isn't as simple as packaging the
modules and pushing them to all the hosts (it is, just not in my network).</p>

<p>My solution is <a href="http://www.silassewell.com/blog/2008/11/18/push-func-module-to-run-arbitrary-python-code/push.py">Push</a>, a Func module which lets you instantly run Python
code on any or all hosts in your network.</p>

<p>Example usage:</p>

<pre><code class="prettyprint">import func.overlord.client as fc

client = fc.Client('web-*.example.net')

source = """
def main():
    return 'Hello World'
"""

print client.push.code(source)
</code></pre>

<p>I realize this isn't the most elegant solution, but its very useful and
extremely simple.</p>

<p>I also realize that I could use the copyfile module to push modules via Func,
but I haven't found a way to restart funcd via Func (required to initialize
modules), so until that happens I need a solution which doesn't require
restarting Func.</p>

<p><a href="http://www.silassewell.com/blog/2008/11/18/push-func-module-to-run-arbitrary-python-code/push.py">Get Push Module</a></p>]]></description>
        </item>

    </channel>
</rss>
