<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:dc="http://purl.org/dc/elements/1.1/"
     xmlns:wfw="http://wellformedweb.org/CommentAPI/"
     >
  <channel>
    <title>Niall O'Higgins</title>
    <link>http://niallohiggins.com/</link>
    <description></description>
    <pubDate>Tue, 03 Apr 2012 18:02:45 GMT</pubDate>
    <generator>Blogofile</generator>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>MongoDB with Python, Pylons, and Pyramid at MongoSF 2011</title>
      <link>http://niallohiggins.com/2011/07/08/mongodb-python-pylons-pyramid-mongosf-2011/</link>
      <pubDate>Fri, 08 Jul 2011 17:04:00 PDT</pubDate>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[MongoDB]]></category>
      <category><![CDATA[Cloud]]></category>
      <guid>http://niallohiggins.com/2011/07/08/mongodb-python-pylons-pyramid-mongosf-2011/</guid>
      <description>MongoDB with Python, Pylons, and Pyramid at MongoSF 2011</description>
      <content:encoded><![CDATA[

<h3>MongoSF 2011</h3>

<p> I was at the <a
  href="https://www.10gen.com/presentation/mongosf-2011/mongodb-with-python-pylons-pyramid">MongoSF
  2011</a> conference in May. Very much enjoyed the 1-day conference, made some
great connections and the 10gen folks hooked me up with O'Reilly to work on a
book "MongoDB and Python", which I hope to have out in a couple of months.
</p>

<h3>My talk: MongoDB with Python, Pylons, and Pyramid</h3>
<p>
I was very happy to be invited to speak at MongoSF.  <a href="https://www.10gen.com/presentation/mongosf-2011/mongodb-with-python-pylons-pyramid">My talk covers using Python with MongoDB</a>, goes into a little bit of detail on the Web frameworks Pylons and Pyramid. <a href="https://www.10gen.com/presentation/mongosf-2011/mongodb-with-python-pylons-pyramid">Watch the video</a>.
</p>
]]></content:encoded>
    </item>
    <item>
      <title>MongoDB with Python, Pyramid and Akhet</title>
      <link>http://niallohiggins.com/2011/05/18/mongodb-python-pyramid-akhet</link>
      <pubDate>Wed, 18 May 2011 12:24:00 PDT</pubDate>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[MongoDB]]></category>
      <category><![CDATA[Pylons]]></category>
      <category><![CDATA[Database]]></category>
      <guid>http://niallohiggins.com/2011/05/18/mongodb-python-pyramid-akhet</guid>
      <description>MongoDB with Python, Pyramid and Akhet</description>
      <content:encoded><![CDATA[

<img src="/images/pyramid-small.png"/>
&nbsp;
<img src="/images/pylonsfw-small.png"/>
<br/>
<h2>Pylons vs Pyramid</h2>
<p>
If you weren't already aware of it, the <a
  href="http://pylonsproject.org">Pylons project</a> has recently sprouted an
all-new Python Web framework called Pyramid. Pyramid is kinda like Pylons 2.0 -
it is a completely new codebase with no code-level backwards compatibility. It
is actually based on <a href="http://bfg.repoze.org/">repoz.bfg</a>.  However, many of the concepts are very similar
to the older Pylons 1.x.
Pyramid is where all the new development is happening, and it has fantastic
code test coverage and documentation. 
</p>

<p>
You can learn more about Pyramid in the <a href="http://docs.pylonsproject.org/faq/pyramid.html">Pyramid FAQ</a>.</p>

<h2>What Is Akhet</h2>

<p> On its own, Pyramid is just a framework - a set of libraries you can use.
Projects are most easily started from a <a
href="http://docs.pylonsproject.org/projects/pyramid/1.0/narr/project.html#paster-templates-included-with-pyramid">template</a>.
A number of different templates are included, offering different persistence
options, URL mappers and session implementations.  </p>

<p>

<b>Akhet</b> is a Pyramid project template (AKA scaffold) which tries to
give you a more Pylons 1.x-like environment. Personally, I'm much more familiar
with Pylons than Pyramid and so Akhet is a great place to start.
</p>

<p>It is well worth your while <a
  href="http://docs.pylonsproject.org/projects/akhet/dev/index.html">reading
  the Akhet documentation</a>. However, the subject of this post, working with
MongoDB, takes advantage of a few changes I have made myself to <a
  href="https://bitbucket.org/niallohiggins/akhet">my Akhet fork on
  BitBucket</a>. I am hoping Mike Orr will accept my changes upstream, but for
now you will need to build the egg from my sources. I will explain how in the next section. </p>

<h2>Starting A Pyramid Project With MongoDB</h2>
<p>
First you need to create a virtual env for your project. Depending on your
platform, you should be able to install the virtualenv tool through a package
manager (sudo port install virtualenv-2.7 in Mac Ports, for example).
</p>

<h3>Install Pyramid</h3>
<p>
Once you have the virtual env tool installed, create the virtualenv, install
Pyramid and its dependencies into it:
</p>

<div class="pygments_murphy"><pre><span class="gp">$</span> mkdir ~/projects/ahket-example
<span class="gp">$</span> virtualenv --no-site-packages myenv
<span class="gp">$</span> <span class="nb">cd </span>myenv
<span class="gp">$</span> <span class="nb">source </span>bin/activate
<span class="gp">$</span> easy_install pyramid
</pre></div>




<h3>Install Akhet</h3>
<p>
Now you have Pyramid and all its dependencies installed. However, you still
need Akhet and its dependencies like PyMongo etc. We are going to use my fork
of Akhet, because it has MongoDB support at the moment.
</p>
<p>
In a new terminal, type the following (you will need Mercurial installed to
fetch the sources from BitBucket):
</p>

<div class="pygments_murphy"><pre><span class="gp">$</span> <span class="nb">cd</span> ~/projects/akhet-example
<span class="gp">$</span> hg clone https://bitbucket.org/niallohiggins/akhet
<span class="gp">$</span> <span class="nb">cd </span>akhet
<span class="gp">$</span> python setup.py sdist
</pre></div>




<p>
Now you have the Akhet with MongoDB support module available. Install it in
your virtual env (go back to original terminal, or re-source
~/projects/akhet-example/myenv/bin/activate):
</p>


<div class="pygments_murphy"><pre><span class="gp">$</span> pip install ~/projects/akhet-example/akhet/dist/Akhet-1.0.1.tar.gz
</pre></div>




<h3>Create Pyramid Project with Akhet and MongoDB Support</h3>
<p>
Okay, great - you can create your Pyramid project now! We shall call it "mongofu".
<br/>

<div class="pygments_murphy"><pre><span class="gp">$</span> <span class="nb">cd</span> ~/projects/akhet-example
<span class="gp">$</span> paster create -t akhet mongofu
<span class="go">Selected and implied templates:</span>
<span class="go">  Akhet#akhet  A Pylons-like Pyramid project</span>

<span class="go">Enter project name: mongofu</span>
<span class="go">Variables:</span>
<span class="go">  egg:      mongofu</span>
<span class="go">  package:  mongofu</span>
<span class="go">  project:  mongofu</span>
<span class="go">Enter sqlalchemy (Include SQLAlchemy configuration? (y/n)) [True]: n</span>
<span class="go">Enter mongodb (Include MongoDB configuration? (y/n)) [False]: y</span>
</pre></div>



</p>

<h3>Install Akhet Dependencies</h3>
<p>
You are just about ready to go. You need to make sure your virtual environment has all the dependencies needed by your mongofu project (e.g. the PyMongo driver). To do so run the following:

<div class="pygments_murphy"><pre><span class="gp">$</span> <span class="nb">cd </span>mongofu ; python setup.py develop
</pre></div>



</p>
<p>
Assuming all went well, you should now have a directory called "mongofu" with a
whole bunch of stuff in it. The default configuration files tell Pyramid to
connect to a MongoDB server on <b>localhost</b>, and a database called
<b>mydb</b>. If you need to change that, simply edit the <b>mongodb.url</b> and
<b>mongodb.db_name</b> settings in the INI-files.
</p>

<h3>Start The Development Server</h3>
<p>
Now try starting up a development server:


<div class="pygments_murphy"><pre><span class="gp">$</span> paster serve development.ini
</pre></div>




If things are working correctly, you should see a message like this on your terminal:

<div class="pygments_murphy"><pre><span class="go">Starting server in PID 6020.</span>
<span class="go">serving on http://127.0.0.1:5000</span>
</pre></div>



</p>

<h2>Talking to MongoDB with Pyramid/Akhet</h2>
<p>

Now you are ready to write some MongoDB queries! Edit the file <b>mongofu/handlers/main.py</b>.

<br/>

In the Main class, we can add a simple query to the "index" action method, referencing the <b>request.db</b> property - which is a handle to our MongoDB database:


<div class="pygments_murphy"><pre><span class="k">class</span> <span class="nc">Main</span><span class="p">(</span><span class="n">base</span><span class="o">.</span><span class="n">Handler</span><span class="p">):</span>
    <span class="nd">@action</span><span class="p">(</span><span class="n">renderer</span><span class="o">=</span><span class="s">&quot;index.html&quot;</span><span class="p">)</span>
    <span class="k">def</span> <span class="nf">index</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="c"># Do some logging.</span>
        <span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&quot;testing logging; entered Main.index()&quot;</span><span class="p">)</span>
        <span class="c"># MongoDB Query</span>
        <span class="c"># can just as easily write request.db.mycollection.find()</span>
        <span class="n">records</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">db</span><span class="p">[</span><span class="s">&#39;mycollection&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">find</span><span class="p">()</span>
        <span class="c"># Push a flash message if query param &#39;flash&#39; is non-empty.</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">params</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&quot;flash&quot;</span><span class="p">):</span>
            <span class="kn">import</span> <span class="nn">random</span>
            <span class="n">num</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">999999</span><span class="p">)</span>
            <span class="n">message</span> <span class="o">=</span> <span class="s">&quot;Random number of the day is:  </span><span class="si">%s</span><span class="s">.&quot;</span> <span class="o">%</span> <span class="n">num</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">flash</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
            <span class="c"># Normally you&#39;d redirect at this point but we have nothing to</span>
            <span class="c"># redirect to.</span>
        <span class="c"># Return a dict of template variables for the renderer.</span>
        <span class="k">return</span> <span class="p">{</span><span class="s">&quot;project&quot;</span><span class="p">:</span><span class="s">&quot;mongofu&quot;</span><span class="p">}</span>
</pre></div>



</p>

<p>
As you can see, we specify a collection in that database to query against. We're not doing anything with the results, but that is enough to demonstrate how to talk to MongoDB with Pyramid and Akhet.
</p>


</p>


]]></content:encoded>
    </item>
    <item>
      <title>MongoDB + Pylons at PyCon 2011</title>
      <link>http://niallohiggins.com/2011/03/18/mongodb-pylons-pycon-2011/</link>
      <pubDate>Fri, 18 Mar 2011 17:04:00 PDT</pubDate>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[MongoDB]]></category>
      <category><![CDATA[Cloud]]></category>
      <guid>http://niallohiggins.com/2011/03/18/mongodb-pylons-pycon-2011/</guid>
      <description>MongoDB + Pylons at PyCon 2011</description>
      <content:encoded><![CDATA[

<h3>PyCon 2011</h3>

<p> I was at the awesome <a href="http://us.pycon.org/2011/home/">PyCon
  2011</a> last week, where I had a fantastic time. Really great conference -
tons of incredible talks and wonderful conversation. Definitely the best
technical conference I've attended. Everyone I met was super friendly,
down-to-earth and just all-around fun.  </p>

<p> Had the pleasure to hang out with the Pylons/Pyramid crew who are a great
bunch. I will certainly be going in 2012, when the event is scheduled to be
held in Santa Clara. Plan to stay for the sprints next time!</p>

<h3>My talk: MongoDB + Pylons at Catch.com</h3>
<p>
I was very happy to be able to present a talk on some of my work at <a href="https://catch.com">Catch.com</a>, where I designed and implemented the platform backend using Pylons and MongoDB. The video of my talk is embedded below:
</p>
<embed src="http://blip.tv/play/g4VigquDWAI%2Em4v" type="application/x-shockwave-flash" width="500" height="405" allowscriptaccess="always" allowfullscreen="true"></embed>
]]></content:encoded>
    </item>
    <item>
      <title>PyMongo 1.7 and MasterSlaveConnection - TypeError breakage</title>
      <link>http://niallohiggins.com/2010/06/22/pymongo-1-7-and-masterslaveconnection-typeerror-breakage/</link>
      <pubDate>Tue, 22 Jun 2010 10:36:01 PDT</pubDate>
      <category><![CDATA[Python]]></category>
      <guid>http://niallohiggins.com/?p=874</guid>
      <description>PyMongo 1.7 and MasterSlaveConnection - TypeError breakage</description>
      <content:encoded><![CDATA[
<img src="http://api.mongodb.org/wiki/current/attachments/132305/1605653.png" alt="mongodb logo" />

<p>
<b>MasterSlaveConnection: Works in Pymongo 1.6</b>
<br/>
In my previous article <a href="http://niallohiggins.com/2010/06/20/python-mongodb-and-pylons-connection-handles-and-all-that-lark/">Python, MongoDB and Pylons,
Connection handles and all that lark</a> I described the code and configuration we use at <a href="http://snaptic.com">Snaptic</a> for working with Pylons and MongoDB. We use the MasterSlaveConnection class to automatically handle read/write splitting, because we expect to be running a single master/multiple slaves configuration in production.
</p>

<p>
<b>Broken in Pymongo 1.7</b>
<br/>
Well, yesterday I upgraded from <a href="http://pypi.python.org/pypi/pymongo">Pymongo</a> 1.6 to Pymongo 1.7 (just released) and found that unfortunately all the MongoDB stuff breaks, throwing TypeError exceptions when issuing even a simple <i>find_one()</i> query. You will see an error like this one:
<code>
TypeError: 'Database' object is not callable. If you meant to call the 'document_class' method on a 'Collection' object it is failing because no such method exists.
</code>
</p>

<p>
<b>But fixed in tip</b>
<br/>
After talking with <a href="http://dirolf.com/">Mike Dirolf</a> (Pymongo author) on the MongoDB IRC channel, he came up with a fix within a few minutes. Although I don't think its in a release yet, if you grab <a href="http://github.com/mongodb/mongo-python-driver/commit/8b76667b4250187a31e6b12df67f4497fc93991d">this commit to Pymongo from github</a>, MasterSlaveConnection should work again. He also <a href="http://jira.mongodb.org/browse/PYTHON-136">filed this bug</a> to come up with a more general solution. Cheers to Mike for his super quick turnaround on fixing the bug!
</p>
]]></content:encoded>
    </item>
    <item>
      <title>Python, MongoDB and Pylons - Connection handles and all that lark</title>
      <link>http://niallohiggins.com/2010/06/20/python-mongodb-and-pylons-connection-handles-and-all-that-lark/</link>
      <pubDate>Sun, 20 Jun 2010 16:35:43 PDT</pubDate>
      <category><![CDATA[Python]]></category>
      <guid>http://niallohiggins.com/?p=856</guid>
      <description>Python, MongoDB and Pylons - Connection handles and all that lark</description>
      <content:encoded><![CDATA[
<img src="http://api.mongodb.org/wiki/current/attachments/132305/1605645.png" alt="mongodb logo" />

<p> I've been doing a bunch of hacking with <a
href="http://www.pylonshq.com">Pylons</a> and <a
href="http://www.mongodb.org/">MongoDB</a> recently for some backend stuff at
<a href="http://snaptic.com">Snaptic</a>. Right now we are using <a
href="http://pythonpaste.org/paste-httpserver-threadpool.html">Paster</a> as
the webserver and the <a
href="http://pypi.python.org/pypi/pymongo/">Pymongo</a> driver. This all works
fine and is pretty straightforward to set up - but there are a couple of
subtleties.  </p>

<b>MongoDB vs SQLAlchemy</b>

<p>
If you've ever used Pylons with <a href="http://www.sqlalchemy.org/">SQLAlchemy</a>, then you've probably noticed the integration is quite good. All of the glue to get access via the global Session object is done for you. With MongoDB and Pylons, the integration isn't quite there yet. You have to set this up yourself.
</p>

<b>Gotta have some replication</b>

<p>
MongoDB doesn't give you the <a href="http://www.mongodb.org/display/DOCS/Durability+and+Repair">same kind of single-server durability guarantees</a> that a RDBMS like MySQL or PostgreSQL does, so you pretty much <a href="http://www.mongodb.org/display/DOCS/Master+Slave">have to use some kind of replication</a> in production. I'm expecting a master/slave configuration, and Pymongo has <a href="http://api.mongodb.org/python/1.6%2B/api/pymongo/master_slave_connection.html#pymongo.master_slave_connection.MasterSlaveConnection">native support for read/write splitting</a> (writes go to the master, reads go to the slave(s)), so I've used that in my Pylons integration code.
</p>

<b>Getting a handle to the database</b>

<p>
The basic idea is that you define a list of masters and slaves in your Pylons config file, and some code in lib/app_globals.py sets up a global handle to the connection object.
</p>

<p>
Here is what I have at the moment, in the <i>__init__</i> method in lib/app_globals.py:
</p>

<pre lang="python" line="1'>
# ... non-pymongo imports omitted
from pymongo import Connection
from pymongo.master_slave_connection import MasterSlaveConnection
from pymongo.errors import ConnectionFailure

# ... class definition, __init__ method etc omitted for brevity ...

# assumption is a master/slave setup for initial production deployment.
# writes should go to the master
# reads should go to the slave(s)
# with sharding, this may change.
def make_conn(host, port, database, username=None, password=None,
        slave_okay=False):
    try:
        conn = Connection(host, port, slave_okay=slave_okay)
    except ConnectionFailure:
        raise Exception('Unable to connect to MongoDB')
    if username and password:
        auth = conn.authenticate(username, password)
        if not auth:
            raise Exception('Authentication to MongoDB failed')
    return conn

username = None
password = None
if 'mongo.username' and 'mongo.password' in config:
    username = config['mongo.username']
    password = config['mongo.password']
master_conn = make_conn(config['mongo.master_host'],
        int(config['mongo.master_port']), username, password)
slaves = []
for i, slave_host in enumerate(config['mongo.slave_hosts'].split(',')):
    slave_port = int(config['mongo.slave_ports'].split(',')[i])
    slave_conn = make_conn(slave_host.strip(), slave_port,
            username, password, slave_okay=True)
    slaves.append(slave_conn)

self.db_conn = MasterSlaveConnection(master_conn, slaves)
self.db = self.db_conn[config['mongo.db']]
</pre>

Then in <i>development.ini</i> I have:

<pre lang="ini" line="1">
# in production, we will write to the master and read from the slaves
mongo.master_host = localhost
mongo.master_port = 27017
# to supply multiple slaves, use comma as the separator.
mongo.slave_hosts = localhost
mongo.slave_ports = 27017

mongo.db = foo

</pre>

Now, to get a handle to the db object from a controller context, you just do the following:

<pre lang="python" line="1">
db = self._py_object.app_globals.db
# now I can go wild and run:
# db.fooCollection.find_one()
</pre>

If you need a handle to the connection object instead, no problem:

<pre lang="python" line="1">
db_conn = self._py_object.app_globals.db_conn
# now I can run:
# db_conn.end_request() if I want.
</pre>

There might be more elegant ways to do this, but this seems to work fine for us. I will write about connection pooling and end_request() next time. Feel free to comment if I left anything out or you have questions!
]]></content:encoded>
    </item>
    <item>
      <title>Autocomplete with Python, Pylons, SQLAlchemy and jQuery</title>
      <link>http://niallohiggins.com/2009/12/21/autocomplete-with-python-pylons-sqlalchemy-and-jquery/</link>
      <pubDate>Mon, 21 Dec 2009 21:51:55 PST</pubDate>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[JavaScript]]></category>
      <guid>http://niallohiggins.com/?p=667</guid>
      <description>Autocomplete with Python, Pylons, SQLAlchemy and jQuery</description>
      <content:encoded><![CDATA[
<p>
Recently I needed to implement my own autocomplete for a project on <a href="http://snagmachine.com">snagmachine.com</a>.  We had a large database of products and wanted to ease data entry by hinting to the user via autocomplete when possible. In future, we can probably just use <a href="http://www.freebase.com/docs/suggest">Freebase Suggest</a> but right now we needed our own solution.
</p>


<p>
<b>The Pieces</b>
<br/>

Autocomplete is not too hard to understand.  It is comprised of two pieces:
<br/>

<ul>
<li>Client-side javascript</li>
<li>Backend web service</li>
</ul>

<p>
<b>Autocomplete JavaScript Widget</b>
<br/>
The client-side JavaScript code is the thing that watches user input to a given text-entry field, and sends queries to the backend web service.  If the backend has some suggestions for the user, the JavaScript then displays those hints and lets the user pick one.
</p>

<p>
Although not hard to understand, the display code and query timing bits of the client-side component make it not utterly trivial to implement.  For this reason, we decided to use an existing jQuery autocomplete widget, instead of writing our own.
</p>

<p>
Choosing one was a little bit confusing, because there are around four or five distinct jQuery autocomplete widgets floating around.  It took some investigation to find one which fit our needs.  We ended up picking <a href="http://www.devbridge.com/projects/autocomplete/jquery/">Ajax Autocomplete for jQuery</a> by Tomas Kirda.
</p>

<p>
We chose this one because it seemed to be the only widget which easily enabled you to pass arbitrary metadata to the client JavaScript from the backend, in addition to mere text completion.  So, if you need to pass along IDs or other values with your suggestions, I recommend this widget instead of some of the simpler ones.
</p>

Setting up the autocomplete widget in your JavaScript is quite straightforward:
<br/>

<pre lang="javascript">
$("#sometextfield").autocomplete({
            serviceUrl:'/api/product_autocomplete',
            onSelect: function(val, data) {
              /* Handle data here */
            },
});
</pre>
</p>

<p>
<b>Backend Web Service</b>
<br/>

Writing an autocomplete web service is pretty simple.  Your entrypoint is going to accept a string of text (query) and return a set of results to be displayed to the user by the autocomplete widget.  Depending on your usage, you may also wish to include some metadata along with your results - for example, the database ID of each completion, or something like that.
</p>

<p>
The service is especially trivial if you are using a database which supports an analog to the SQL LIKE/ILIKE operator which does basic wild-card text matching.  I believe that all databases supported by <a href="http://sqlalchemy.org">SQLAlchemy</a> will have this feature. 
</p>

<p>
Although I happened to be using SQLAlchemy and a fairly traditional RDBMS (<a href="http://www.postgresql.org">PostgreSQL</a>) for snagmachine.com, something similar should be quite possible with <a href="http://1978th.net/tokyotyrant/">Tokyo Tyrant</a> and the like.
</p>

<p>
We are using <a href="http://pylonshq.com">Pylons</a> and SQLAlchemy for snagmachine.com, but again, it shouldn't be much more complicated with some other web framework:
</p>

<pre lang="python">
    @rest.restrict('GET')
    @jsonify
    def tag_autocomplete(self):
        if 'query' not in request.params:
            abort(400)
        fragment = request.params['query']
        keywords = fragment.split()
        searchstring = "%%".join(keywords)
        searchstring = '%%%s%%' %(searchstring)
        try:
            ac_q = Session.query(Tag)
            res = ac_q.filter(Tag.name.ilike(searchstring)).limit(10)
            return dict(query=fragment,
                    suggestions=[r.name for r in res],
                    data=["%s" %(r.name) for r in res])
        except NoResultFound:
            return dict(query=fragment, suggestions=[], data=[])

</pre>
<br/>

In the above code, we are using a very simple SQLAlchemy model class "Tag" which basically consists of a text `name' field:
<pre lang="python">
tag_table = sa.Table("tag", meta.metadata,
    sa.Column("id", types.Integer, sa.schema.Sequence('taq_seq_id',
        optional=True), primary_key=True),
    sa.Column("name", types.Unicode(50), nullable=False, unique=True),
    sa.Column("extra", types.String),
)
class Tag(object):
    pass
orm.mapper(Tag, tag_table)
</pre>
<p>
  We also use the <a href="http://pylonshq.com/docs/en/0.9.7/modules/decorators_rest/">Pylons rest decorator</a> and the <a href="http://pylonshq.com/docs/en/0.9.7/modules/decorators/#pylons.decorators.jsonify">Pylons jsonify decorator</a> for convenience.
</p>
<br/>

Note that in the above code, we:
<br/>

<ul>
<li>Use the ilike operator</li>
<li>Use wildcards at the beginning and end of the string</li>
<li>Replace whitespace with wildcards</li>
</ul>

<p>
We've found this mode to give us the best user experience, however there are performance implications.  PostgreSQL at least can only utilise text indexes for LIKE, and furthermore only if the wildcards are suffixes [<a href="http://markmail.org/message/ibuw5poeqysiv4h3">This email from Tom Lane has the details</a>].
</p>

<p>
While using the index does yield about an order of magnitude difference in query response time, we are talking about 0.1 ms vs 1.0 ms with our dataset.  For our use case, this is perfectly acceptable!
</p>

<p>
So, thats pretty much everything there is to it.  Hope this article helps!
</p>
]]></content:encoded>
    </item>
    <item>
      <title>Pylons tip #5 - Streaming static files</title>
      <link>http://niallohiggins.com/2009/11/04/pylons-tip-5-streaming-static-files/</link>
      <pubDate>Wed, 04 Nov 2009 19:15:29 PST</pubDate>
      <category><![CDATA[Technical]]></category>
      <category><![CDATA[Python]]></category>
      <guid>http://niallohiggins.com/?p=656</guid>
      <description>Pylons tip #5 - Streaming static files</description>
      <content:encoded><![CDATA[
Pylons makes it super easy to return data to a client.  You just return a string from your controller method!

<pre lang="python">
class HelloController(BaseController):

    def index(self):
        return 'Hello World!'

</pre>

Very nice.  However, what if you want to serve up a potentially quite large file to the client?  Sure, you could read the file into memory, and then return the entire buffer, but that is not very efficient.  If you have a multi-megabyte file, you end up wasting lots of memory.

What you want to do, actually, is read a chunk of the file at a time, and then send that.  So instead of reading the entire file into memory and returning it in a single go, you do lots of little chunks.

Simple conceptually.  How do you do this in Pylons?  Thankfully <a href="http://docs.pythonweb.org/display/pylonsfaq/Streaming+Content+to+the+Browser">you can do this with a Python generator</a>.  Instead of returning a buffer, you return a generator:

<pre lang="python">
class ImageController(BaseController):

    def index(self, id):
        ''' Stream local image contents to client '''
        try:
            imgf = open("%s/%s" %(config['image_data_dir'],
                os.path.basename(id)), 'r')
        except IOError:
            abort(404)
        def stream_img():
            chunk = imgf.read(1024)
            while chunk:
                yield chunk
                chunk = imgf.read(1024)
            imgf.close()
        return stream_img()
</pre>

This works quite nicely.  Hope that helps!]]></content:encoded>
    </item>
    <item>
      <title>Simple Python Twitter Search API Crawler Class</title>
      <link>http://niallohiggins.com/2009/09/27/simple-python-twitter-search-api-crawler-class/</link>
      <pubDate>Sun, 27 Sep 2009 15:55:54 PDT</pubDate>
      <category><![CDATA[Python]]></category>
      <guid>http://niallohiggins.com/?p=579</guid>
      <description>Simple Python Twitter Search API Crawler Class</description>
      <content:encoded><![CDATA[
I've been getting into <a href="http://twitter.com">Twitter</a> (I'm <a href="http://twitter.com/niallohiggins">@niallohiggins</a> btw) a bit recently.  One of the things I wanted to do was write a little program to periodically search for a specific tag and then process the results.  The <a href="http://apiwiki.twitter.com/Twitter-Search-API-Method:-search">Twitter Search API</a> is very easy to use, even if there are <a href="http://code.google.com/p/twitter-api/issues/detail?id=214">some annoying issues</a>.

Here is a very simple class I wrote to issue searches and return the results. It also keeps track of the last high water mark (max_id) of the previous search, so you hopefully won't get the same results twice - although you still want to code defensively for that <a href="http://code.google.com/p/twitter-api/issues/detail?id=834">in case there is a bug in Twitter</a>. Feel free to use this code yourself.  Note that you'll have to implement your own 'submit' method.

<pre lang="python">
import httlib
import json
import logging
import socket
import time
import urllib

SEARCH_HOST="search.twitter.com"
SEARCH_PATH="/search.json"


class TagCrawler(object):
    ''' Crawl twitter search API for matches to specified tag.  Use since_id to
    hopefully not submit the same message twice.  However, bug reports indicate
    since_id is not always reliable, and so we probably want to de-dup ourselves
    at some level '''

    def __init__(self, max_id, tag, interval):
        self.max_id = max_id
        self.tag = tag
        self.interval = interval
        
    def search(self):
        c = httplib.HTTPConnection(SEARCH_HOST)
        params = {'q' : self.tag}
        if self.max_id is not None:
            params['since_id'] = self.max_id
        path = "%s?%s" %(SEARCH_PATH, urllib.urlencode(params))
        try:
            c.request('GET', path)
            r = c.getresponse()
            data = r.read()
            c.close()
            try:
                result = json.loads(data)
            except ValueError:
                return None
            if 'results' not in result:
                return None
            self.max_id = result['max_id']
            return result['results']
        except (httplib.HTTPException, socket.error, socket.timeout), e:
            logging.error("search() error: %s" %(e))
            return None

    def loop(self):
        while True:
            logging.info("Starting search")
            data = self.search()
            if data:
                logging.info("%d new result(s)" %(len(data)))
                self.submit(data)
            else:
                logging.info("No new results")
            logging.info("Search complete sleeping for %d seconds"
                    %(self.interval))
            time.sleep(float(self.interval))

    def submit(self, data):
        pass

</pre>]]></content:encoded>
    </item>
    <item>
      <title>Py Web SF: The San Francisco Python & Web Technology Meet-up</title>
      <link>http://niallohiggins.com/2009/07/24/py-web-sf-the-san-francisco-python-web-technology-meet-up/</link>
      <pubDate>Fri, 24 Jul 2009 19:29:47 PDT</pubDate>
      <category><![CDATA[Technical]]></category>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[UNIX]]></category>
      <category><![CDATA[JavaScript]]></category>
      <category><![CDATA[Windows]]></category>
      <guid>http://niallohiggins.com/?p=563</guid>
      <description>Py Web SF: The San Francisco Python & Web Technology Meet-up</description>
      <content:encoded><![CDATA[
Last month I started <a href="http://pywebsf.org">Py Web SF</a>, the San Francisco Python & Web Technology meet-up.  The idea is 1-2 conversation-style presentations of about 30 minutes with a group of 10-20 people.  My hope is to have a more intimate group than the very good <a href="http://www.baypiggies.net/">Bay Piggies</a> (which I highly recommend).  With a small group, it is possible to have more interaction, discussion and collaboration.  In a typical lecture/audience format, people unfortunately tend to switch into "passive listener" mode.

<p>
<a href="http://pywebsf.org"><img src="http://niallohiggins.com/wp-content/uploads/2009/07/pywebsf.png" alt="pywebsf" title="pywebsf" width="321" height="156" class="aligncenter size-full wp-image-566" /></a>
</p>

<p>
<strong>June meet-up</strong>
<br/>

Anyway, the first meet-up went extremely well - we had 15 people show up, which was a perfect number for the space.  <a href="http://jjinux.blogspot.com/">Shannon -jj Behrens</a> gave an excellent talk on <A href="http://www.pywebsf.org/2009/06/24/shannon-jj-behrens-techniques-for-building-third-party-restful-web-services/">building RESTful Web services</a> and <a href="http://monkey.org/~marius">Marius Eriksen</a> - in fact a colleague from the <a href="http://www.openbsd.org">OpenBSD project</a> - gave an <a href="http://www.pywebsf.org/2009/06/24/marius-a-eriksen-geodjango-a-world-class-geographic-web-framework/">awesome talk on GeoDjango</a>.  Slides for both talks are online, of course.
</p>

<p>
<strong>July meet-up</strong>
<br/>

<a href="http://www.pywebsf.org/2009/07/21/py-web-sf-2-july-28th-6pm-sf-main-public-library%e2%80%99s-stong-room/'>This month's meet</a> should be equally good.  We have two great talks lined up - Aseem Mohanty, a colleague of mine from <a href="http://www.metaweb.com">Metaweb Technologies</a> presenting a comparison of Django and Pylons.  Then we have Alec Flett, another Metaweb'er, speaking about all the issues involved in scaling Python web applications.
</p>

<p>
<strong>Check it out</strong>
<br/>

If you are interested in checking out the event, its <b>July 28th, 6pm @ SF Main Public Libraryâ€™s Stong Room</b>.  Full details can be found <a href=" http://www.pywebsf.org/2009/07/21/py-web-sf-2-july-28th-6pm-sf-main-public-library%E2%80%99s-stong-room/">at pywebsf.org</a>. Or if you are interested in giving a talk, <a href="mailto:niallo@pywebsf.org">just let me know</a>.
</p>
]]></content:encoded>
    </item>
    <item>
      <title>Turbo Gears 2.0 Released</title>
      <link>http://niallohiggins.com/2009/05/27/turbo-gears-20-released/</link>
      <pubDate>Wed, 27 May 2009 18:30:20 PDT</pubDate>
      <category><![CDATA[Technical]]></category>
      <category><![CDATA[Python]]></category>
      <guid>http://niallohiggins.com/?p=535</guid>
      <description>Turbo Gears 2.0 Released</description>
      <content:encoded><![CDATA[
<a href="http://www.turbogears.org"><img src="http://niallohiggins.com/wp-content/uploads/2009/05/tg.png" alt="Turbo Gears 2.0" title="Turbo Gears 2.0" width="198" height="192" class="aligncenter size-full wp-image-536" /></a>

<p>
I read today that <a href="http://www.turbogears.org/2.0/docs/main/WhatsNew.html">Turbo Gears 2.0 has been released</a> - at long last!  I used Turbo Gears 1 briefly in 2007 for a small project then switched to <a href="http://www.pylonshq.com">Pylons</a>. 
</p>

<p>
Pylons is pretty neat because its really a framework for building a framework.  You can pick and choose <a href="http://en.wikipedia.org/wiki/Web_Server_Gateway_Interface">WSGI middleware</a> and slot it all together with whatever templating engine or database abstraction layer you like. Pylons just gives you most of the glue you'd need - stuff like unit and functional test harnesses, request routing, caching, and various handy decorators. The Pylons approach has some disadvantages however, since its not quite as well integrated as say <a href="http://www.djangoproject.com/">Django</a>, which has more of a one-size-fits-all, monolithic approach.  Pylons also has <a href="http://www.pylonsbook.com">excellent documentation</a>.
</p>

<p>
Its interesting that Turbo Gears 2.0 is <b>built on top of Pylons</b>.  It seems to aim to provide you with a more consistent out-of-the-box solution - they standardise on one templating language (Genshi), one database abstraction layer (SQLAlchemy), etc.
</p>

<p>
It will be interesting to see where Turbo Gears goes from here.  It could be quite compelling if the community catches on, but it seems to me that its a little late to the game.  I'm not certain what jumping to Turbo Gears 2.0 from Pylons would buy me at this point, and I'd imagine many people feel the same way.
</p>
]]></content:encoded>
    </item>
  </channel>
</rss>

