<?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/"
	xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>WebMynd Blog</title>
	<atom:link href="http://blog.webmynd.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.webmynd.com</link>
	<description></description>
	<lastBuildDate>Thu, 15 Oct 2009 19:27:03 +0000</lastBuildDate>
	<generator>http://wordpress.com/</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<cloud domain='blog.webmynd.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://www.gravatar.com/blavatar/26f4c01a4db7094960cef3c986f19c47?s=96&#038;d=http://s.wordpress.com/i/buttonw-com.png</url>
		<title>WebMynd Blog</title>
		<link>http://blog.webmynd.com</link>
	</image>
			<item>
		<title>Rules for RedesignGoogle.com competition</title>
		<link>http://blog.webmynd.com/2009/10/15/rules-for-redesigngoogle-com-competition/</link>
		<comments>http://blog.webmynd.com/2009/10/15/rules-for-redesigngoogle-com-competition/#comments</comments>
		<pubDate>Thu, 15 Oct 2009 17:12:01 +0000</pubDate>
		<dc:creator>amirnathoo</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.webmynd.com/?p=201</guid>
		<description><![CDATA[RedesignGoogle is run by WebMynd Corp. Contact us anytime with your questions.
(1) By taking part in the competition, you warrant that all information submitted is true, current and complete at the time of submission. You also warrant that the CSS and all images and artifacts linked from it (&#8220;your submission&#8221;), is your own work. It [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.webmynd.com&blog=2592024&post=201&subd=webmynd&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><a title="RedesignGoogle" href="http://redesigngoogle.com">RedesignGoogle</a> is run by <a title="WebMynd" href="http://www.webmynd.com">WebMynd</a> Corp. <a title="Contact us" href="http://www.webmynd.com/html/contact.html">Contact us anytime with your questions</a>.</p>
<p>(1) By taking part in the competition, you warrant that all information submitted is true, current and complete at the time of submission. You also warrant that the CSS and all images and artifacts linked from it (&#8220;your submission&#8221;), is your own work. It is your sole responsibility to ensure that your details and e-mail address are accurate, and that WebMynd Corp. is informed of any changes to these. WebMynd Corp accepts no responsibility for any changes which are not properly notified from the time of submission of your entry to the time of notification that the prize has been awarded.</p>
<p>(2) You may make multiple submissions.</p>
<p>(3) Your submission remains your property. By submitting your entry to the competition you assign WebMynd Corp a perpetual license to distribute your submission.</p>
<p>(4) WebMynd Corp. reserves the right to disqualify your entry if it is incomplete or if there are reasonable grounds to believe that you have breached any of these rules.</p>
<p>(5) For consideration in the competition your submission must be received by WebMynd Corp. via the <a title="RedesigGoogle Editor" href="http://www.webmynd.com/look/designs/edit" target="_self">RedesignGoogle editor</a> by midnight PST on December 1 2009. The winning submission will be announced before December 15 2009 on WebMynd Corp&#8217;s blog and redesigngoogle.com. The prize will be delivered within 30 days of announcement of the winning submission.</p>
<p>(6) The prize for the winning submission is a Macbook Air. Prizes for runners-up may be awarded at WebMynd Corp&#8217;s sole discretion.</p>
<p>(7) The winning submission will be selected from a shortlist by a panel of judges. The shortlist will be determined soley by WebMynd Corp at it&#8217;s own discretion, and this will be influenced by the number of rating stars, comments and downloads that your submission attracts. The panel of judges will consist of WebMynd Corp., Paul Graham and Jason Kincaid.</p>
<p>(8) Prizes are non-transferable and there are no cash alternatives. WebMynd Corp. reserves the right to substitute prizes of equal or greater value at any time. All taxes, insurances, transfers and other expenses resulting from the prize are the sole responsibility of the winner unless otherwise stated.</p>
<p>(9) Failure to claim a prize within the time or in the manner specified may result in disqualification and the selection of an alternative winner.</p>
<p>(10) WebMynd Corp reserves the right to alter, amend or close the competition as necessary.</p>
<p>(11) In the case of any disputes regarding these rules, or the rules or instructions of a specific competition, the decision of WebMynd Corp. will be final and binding, and no correspondence will be entered into.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/webmynd.wordpress.com/201/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/webmynd.wordpress.com/201/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/webmynd.wordpress.com/201/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/webmynd.wordpress.com/201/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/webmynd.wordpress.com/201/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/webmynd.wordpress.com/201/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/webmynd.wordpress.com/201/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/webmynd.wordpress.com/201/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/webmynd.wordpress.com/201/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/webmynd.wordpress.com/201/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.webmynd.com&blog=2592024&post=201&subd=webmynd&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://blog.webmynd.com/2009/10/15/rules-for-redesigngoogle-com-competition/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e5dd580fed4e3a3924b4c3b5c4f242ad?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">amirnathoo</media:title>
		</media:content>
	</item>
		<item>
		<title>RedesignGoogle</title>
		<link>http://blog.webmynd.com/2009/09/16/redesigngoogle/</link>
		<comments>http://blog.webmynd.com/2009/09/16/redesigngoogle/#comments</comments>
		<pubDate>Wed, 16 Sep 2009 22:21:38 +0000</pubDate>
		<dc:creator>Imran Zaidi</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.webmynd.com/?p=156</guid>
		<description><![CDATA[One of our key goals at WebMynd is to give you more control over your search experience. Our first steps toward that were to outfit our add-on with our own set of customizable search interfaces. Now we&#8217;re excited to announce our next step: RedesignGoogle.
RedesignGoogle lets you completely customize the look of Google Search by installing [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.webmynd.com&blog=2592024&post=156&subd=webmynd&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>One of our key goals at <a href="http://www.webmynd.com">WebMynd</a> is to give you more control over your search experience. Our first steps toward that were to outfit our <a href="http://webmynd.com/html/WebMynd-0.9.xpi">add-on</a> with our own set of customizable <a href="http://blog.webmynd.com/2009/09/16/new-in-0-9-manhattan-and-osaka/">search interfaces</a>. Now we&#8217;re excited to announce our next step: <a href="http://redesigngoogle.com">RedesignGoogle</a>.</p>
<p>RedesignGoogle lets you completely customize the look of Google Search by installing user-submitted designs from an <a href="http://www.webmynd.com/look/designs">online gallery</a>. A stripped-down version of the WebMynd add-on applies your installed stylesheet whenever you&#8217;re on a Google search results page. (You can enable WebMynd&#8217;s other features if you like, but they&#8217;re turned off by default.) Currently, RedesignGoogle is available for Firefox, and we&#8217;ll be releasing versions of the add-on for other browsers soon.</p>
<p>If you&#8217;re a designer, this is your chance to revamp the most widely used service on the web. Anything that can be manipulating using CSS can be changed with RedesignGoogle; here are a <a href="http://webmynd.com/look/designs/by_id/62">couple</a> of <a href="#">examples</a> of what&#8217;s possible. We offer a web-based <a href="#">CSS editor</a> for creating and previewing your designs, but you&#8217;re free to use your preferred tools &#8212; just paste your stylesheet into the editor when you&#8217;re ready to apply it to your own searches and publish it to the <a href="http://www.webmynd.com/look/designs">Gallery</a>.</p>
<p>Most exciting of all: we&#8217;ll be holding a competition to find the best user-submitted designs. The winner will receive a new <strong>MacBook Air</strong>; runners-up will get something cool too. Designs will be judged by <a href="http://paulgraham.com">Paul Graham</a>, the WebMynd team, and a few others TBA. Stay tuned for more details and official rules.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/webmynd.wordpress.com/156/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/webmynd.wordpress.com/156/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/webmynd.wordpress.com/156/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/webmynd.wordpress.com/156/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/webmynd.wordpress.com/156/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/webmynd.wordpress.com/156/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/webmynd.wordpress.com/156/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/webmynd.wordpress.com/156/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/webmynd.wordpress.com/156/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/webmynd.wordpress.com/156/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.webmynd.com&blog=2592024&post=156&subd=webmynd&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://blog.webmynd.com/2009/09/16/redesigngoogle/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/19a10c0b4840e54c44e6cec77dcb9f14?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">izaidi</media:title>
		</media:content>
	</item>
		<item>
		<title>New in 0.9: Manhattan and Osaka</title>
		<link>http://blog.webmynd.com/2009/09/16/new-in-0-9-manhattan-and-osaka/</link>
		<comments>http://blog.webmynd.com/2009/09/16/new-in-0-9-manhattan-and-osaka/#comments</comments>
		<pubDate>Wed, 16 Sep 2009 22:17:36 +0000</pubDate>
		<dc:creator>Imran Zaidi</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.webmynd.com/?p=147</guid>
		<description><![CDATA[Available in the new 0.9 release of the WebMynd Firefox add-on are two new experimental search interfaces, Manhattan and Osaka:


These new interfaces were designed based on some of the feedback we received on our first experimental interface, Phoenix. In contrast to Phoenix, which minimizes visual clutter by only presenting the top three results from each [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.webmynd.com&blog=2592024&post=147&subd=webmynd&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Available in the new <a href="http://webmynd.com/html/WebMynd-0.9.xpi">0.9 release</a> of the WebMynd Firefox add-on are two new experimental search interfaces, <strong>Manhattan</strong> and <strong>Osaka</strong>:</p>
<p><img class="screenshot1" title="Manhattan" src="http://crckrjck.com/screenmanhattan.png" alt="" width="400" height="237" /></p>
<p><img class="screenshot2" title="Osaka" src="http://crckrjck.com/screenosaka.png" alt="" width="400" height="237" /></p>
<p>These new interfaces were designed based on some of the feedback we received on our first experimental interface, <a href="http://blog.webmynd.com/2009/08/17/a-new-way-to-look-at-search/">Phoenix</a>. In contrast to Phoenix, which minimizes visual clutter by only presenting the top three results from each of your selected sources on the main screen, Manhattan and Osaka display all your results within scrollable frames in a magazine-style layout. The idea is to let you browse the most possible information with the least possible interaction.</p>
<p>We&#8217;re just getting started with these features, and there&#8217;s a lot of work yet to be done. But we hope that by offering new kinds of search experiences we can help improve one of the most important (and often most frustrating) aspects of using the web.</p>
<p>Install <a href="http://webmynd.com/html/WebMynd-0.9.xpi">WebMynd 0.9</a> to try our new interfaces on your own searches.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/webmynd.wordpress.com/147/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/webmynd.wordpress.com/147/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/webmynd.wordpress.com/147/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/webmynd.wordpress.com/147/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/webmynd.wordpress.com/147/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/webmynd.wordpress.com/147/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/webmynd.wordpress.com/147/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/webmynd.wordpress.com/147/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/webmynd.wordpress.com/147/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/webmynd.wordpress.com/147/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.webmynd.com&blog=2592024&post=147&subd=webmynd&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://blog.webmynd.com/2009/09/16/new-in-0-9-manhattan-and-osaka/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/19a10c0b4840e54c44e6cec77dcb9f14?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">izaidi</media:title>
		</media:content>

		<media:content url="http://crckrjck.com/screenmanhattan.png" medium="image">
			<media:title type="html">Manhattan</media:title>
		</media:content>

		<media:content url="http://crckrjck.com/screenosaka.png" medium="image">
			<media:title type="html">Osaka</media:title>
		</media:content>
	</item>
		<item>
		<title>A new way to look at search</title>
		<link>http://blog.webmynd.com/2009/08/17/a-new-way-to-look-at-search/</link>
		<comments>http://blog.webmynd.com/2009/08/17/a-new-way-to-look-at-search/#comments</comments>
		<pubDate>Mon, 17 Aug 2009 20:14:28 +0000</pubDate>
		<dc:creator>Imran Zaidi</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.webmynd.com/?p=140</guid>
		<description><![CDATA[We&#8217;ve been working on some exciting new features over the last few weeks. One of them is Phoenix, an experimental new search interface that offers the functionality of Google and the WebMynd sidebar with a clean and engaging look and feel.

Phoenix is the first of several new interfaces we&#8217;re working on. Our hope is that [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.webmynd.com&blog=2592024&post=140&subd=webmynd&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>We&#8217;ve been working on some exciting new features over the last few weeks. One of them is Phoenix, an experimental new search interface that offers the functionality of Google and the WebMynd sidebar with a clean and engaging look and feel.</p>
<p><img class="screenshot" title="Phoenix" src="http://webmynd.com/html/images/screenphoenix.png" alt="" width="400" height="237" /></p>
<p>Phoenix is the first of several new interfaces we&#8217;re working on. Our hope is that each will offer a unique experience, so that you can choose the one that&#8217;s best suited to the way you search. We think Google&#8217;s interface has grown stale from a lack of innovation and there&#8217;s a wide range of design possibilities that have yet to be explored. Our lead designer, Imran Zaidi, has written an <a href="http://type.crckrjck.com/1">article</a> outlining the thinking behind Phoenix and its underlying design framework.</p>
<p>Phoenix is included in the new <a href="http://webmynd.com/html/WebMynd-0.8.3.xpi">0.8.3 release</a> of the WebMynd extension for Firefox.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/webmynd.wordpress.com/140/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/webmynd.wordpress.com/140/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/webmynd.wordpress.com/140/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/webmynd.wordpress.com/140/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/webmynd.wordpress.com/140/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/webmynd.wordpress.com/140/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/webmynd.wordpress.com/140/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/webmynd.wordpress.com/140/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/webmynd.wordpress.com/140/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/webmynd.wordpress.com/140/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.webmynd.com&blog=2592024&post=140&subd=webmynd&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://blog.webmynd.com/2009/08/17/a-new-way-to-look-at-search/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/19a10c0b4840e54c44e6cec77dcb9f14?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">izaidi</media:title>
		</media:content>

		<media:content url="http://webmynd.com/html/images/screenphoenix.png" medium="image">
			<media:title type="html">Phoenix</media:title>
		</media:content>
	</item>
		<item>
		<title>Backing SQLAlchemy models with S3</title>
		<link>http://blog.webmynd.com/2009/07/19/backing-sqlalchemy-models-with-s3/</link>
		<comments>http://blog.webmynd.com/2009/07/19/backing-sqlalchemy-models-with-s3/#comments</comments>
		<pubDate>Sun, 19 Jul 2009 19:04:53 +0000</pubDate>
		<dc:creator>James Brady</dc:creator>
				<category><![CDATA[technical]]></category>
		<category><![CDATA[aws]]></category>
		<category><![CDATA[boto]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[s3]]></category>
		<category><![CDATA[sqlalchemy]]></category>

		<guid isPermaLink="false">http://blog.webmynd.com/?p=126</guid>
		<description><![CDATA[Relational databases, and the object-relational mapping layers which abstract them, are not particularly well suited to storing large blobs of data: images, videos, pictures, compressed files and so on.
Far better than streaming megabytes of binary to the database is to instead keep a reference into a separate store, better suited to the task of saving [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.webmynd.com&blog=2592024&post=126&subd=webmynd&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Relational databases, and the object-relational mapping layers which abstract them, are not particularly well suited to storing large blobs of data: images, videos, pictures, compressed files and so on.</p>
<p>Far better than streaming megabytes of binary to the database is to instead keep a reference into a separate store, better suited to the task of saving and serving files.</p>
<p>At <a href="http://webmynd.com/">WebMynd</a>, we use <a href="http://www.sqlalchemy.org/">SQLAlchemy</a> as our ORM and Amazon&#8217;s <a href="http://aws.amazon.com/s3/">Simple Storage Service</a> (S3) to store our files. We&#8217;ve used <a href="http://code.google.com/p/boto/">Boto</a> to create a convenient, transparent way to store a file in SQLAlchemy, with the actual data of the file actually residing in S3. These files can then be served directly from S3, decreasing database size and I/O load, and potentially reducing bandwidth costs.</p>
<h2>Transparent changes to file content</h2>
<p>Suppose the objects we wish to be backed by S3 have a <span style="font-family:monospace;">content</span> attribute, which is the file body itself. What we&#8217;re aiming for is to be able to do something like:</p>
<pre>file = session.query(File).get(file_id)
file.content="new content"
session.save_or_update(file)
session.flush()</pre>
<p>This can be achieved by creating a property on the SQLAlchemy model class:</p>
<pre>    def _set_content(self, cont):
        s3     = boto.connect_s3(aws_id, aws_key)
        bucket = s3.get_bucket(s3_bucket)
        key    = bucket.get_key(self.key)
        if not key:
            key = Key(bucket=bucket, name=self.key)
        key.set_contents_from_string(cont)
        # if you want to serve files directly from S3:
        key.make_public()
    def _get_content(self):
        s3     = boto.connect_s3(aws_id, aws_key)
        bucket = s3.get_bucket(s3_bucket)
        key    = bucket.get_key(self.key)
        if not key:
            pass # complain
        else:
            return key.get_contents_as_string()
    content = property(_get_content, _set_content)</pre>
<h2>Cleaning up S3 artifacts</h2>
<p>The task of keeping S3 synchronised with the database state seems like it would be awkward, perhaps involving database triggers and queues of reconciliation tasks. I was pleasantly surprised to find that SQLAlchemy has an excellent <a href="http://www.sqlalchemy.org/docs/05/reference/orm/interfaces.html#sqlalchemy.orm.interfaces.MapperExtension">MapperExtension</a> class, which gives you a bunch of hooks to hang custom code off. For example, to delete an S3 key when a SQLAlchemy <span style="font-family:monospace;">File</span> object is deleted, you would do something like:</p>
<pre>class CleanupS3(MapperExtension):
    def after_delete(self, mapper, conn, inst):
        s3     = boto.connect_s3(aws_id, aws_key)
        bucket = s3.get_bucket(s3_bucket)
        key    = bucket.get_key(inst.key)
        if key:
            key.delete()
        else:
            pass # complain
        return orm.EXT_CONTINUE

mapper(File, file_table, extension=CleanupS3())</pre>
<p>A script with a working example can be found <a href="http://webmynd_public.s3.amazonaws.com/s3_backed_sqla.py">here</a>. It requires Boto, SQLAlchemy and some AWS configuration. In real-world usage, you&#8217;d want some more error-checking, handling of mime types and you may choose to stream in the file content with Boto&#8217;s <span style="font-family:monospace;">set_contents_from_file</span> method. You&#8217;ll also note that we <span style="font-family:monospace;">connect</span> to S3 for every method invocation; if you have frequent changes to file content, using a connection pool for Boto might help improve performance.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/webmynd.wordpress.com/126/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/webmynd.wordpress.com/126/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/webmynd.wordpress.com/126/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/webmynd.wordpress.com/126/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/webmynd.wordpress.com/126/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/webmynd.wordpress.com/126/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/webmynd.wordpress.com/126/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/webmynd.wordpress.com/126/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/webmynd.wordpress.com/126/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/webmynd.wordpress.com/126/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.webmynd.com&blog=2592024&post=126&subd=webmynd&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://blog.webmynd.com/2009/07/19/backing-sqlalchemy-models-with-s3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/363e08c01d9caf37d45bf6e5a011421b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jamesbrady</media:title>
		</media:content>
	</item>
		<item>
		<title>Modularising your code deployment</title>
		<link>http://blog.webmynd.com/2009/04/13/modularising-your-code-deployment/</link>
		<comments>http://blog.webmynd.com/2009/04/13/modularising-your-code-deployment/#comments</comments>
		<pubDate>Mon, 13 Apr 2009 22:41:22 +0000</pubDate>
		<dc:creator>James Brady</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[distutils]]></category>
		<category><![CDATA[easy_install]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[setuptools]]></category>
		<category><![CDATA[turbog]]></category>
		<category><![CDATA[turbogears]]></category>

		<guid isPermaLink="false">http://blog.webmynd.com/?p=119</guid>
		<description><![CDATA[Most software projects start with a nice, clean, compartmentalised architecture, whether real or imagined. As implementation progresses, the lines between components tend to blur as unforeseen dependencies emerge and edge cases are dealt with.
However, by the time it comes to deployment, you&#8217;ll probably still have a number of separate packages, with some (hopefully acyclic) dependency [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.webmynd.com&blog=2592024&post=119&subd=webmynd&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Most software projects start with a nice, clean, compartmentalised architecture, whether real or imagined. As implementation progresses, the lines between components tend to blur as unforeseen dependencies emerge and edge cases are dealt with.</p>
<p>However, by the time it comes to deployment, you&#8217;ll probably still have a number of separate packages, with some (hopefully acyclic) dependency graph binding them together.</p>
<p>At <a href="http://www.webmynd.com/html/">WebMynd</a>, the web tier runs on <a href="http://turbogears.org/">Turbogears</a>, a <a href="http://python.org/">Python</a> web framework. Turbogears is by its nature very modular, with various options for &#8220;plugging in&#8221; alternative tools and extensions, which has led us to be quite modular with our own code.</p>
<p>Dependencies between these packages is managed via the <strong>install_requires</strong> <a href="http://peak.telecommunity.com/DevCenter/setuptools">setuptools</a> parameters, e.g.:</p>
<pre>    install_requires=[
        "TurboGears",
        "SQLAlchemy",
        "MiniMock &gt;= 1.2.2",
        "Boto &gt;= 1.5",
        "Sphinx",
        "WMQueueLib",
        "WMModel",
    ],</pre>
<p>Here, the <strong>&#8220;WM&#8230;&#8221; </strong>packages are internal, and we don&#8217;t really want to share them on <a href="http://pypi.python.org/pypi/">PyPI</a>. So how best to get them installed onto the machines where they&#8217;re required?</p>
<p>One option is to grab the source code directly, build and install it into place. Even if your code is in a <a href="http://en.wikipedia.org/wiki/DVCS">DVCS</a>, this process can complex, and you&#8217;re going to have to store somewhere the URLs and/or levels that each package depends on from the others. But this information is already encoded in a much more concise and flexible way: the <strong>install_requires</strong> declarations!</p>
<p>We&#8217;ve found it convenient to take advantage of this version-controlled dependency graph by hosting our own little package index internally. It&#8217;s nice and easy: all that&#8217;s required is some <strong>easy_install</strong> configuration like this:</p>
<pre>[easy_install]
find_links = http://internal_server.webmynd.com/packages/</pre>
<p>Our <em>internal_server</em> is only accessible from a restricted set of IPs, but you could use other security measures &#8211; I&#8217;ve just tried basic HTTP authentication and it works: just prepend <strong>username:password@</strong> to the domain.</p>
<p>There are a few places you can put this configuration, but we include it in <strong>setup.cfg</strong> in all our packages, so that install dependencies just take care of themselves, with no hassle and no changes required on the machines. Installing a package is as simple as:</p>
<pre>easy_install WMWebTier</pre>
<p>Rather than making sure that the right source is pulled down on the right machine at the right time, now you can safely push all your good builds up onto your internal package index and trust that the client selects the right one. You&#8217;ve already encoded dependencies in your package metadata &#8211; relax and let <strong>easy_install </strong>do the hard work for you!</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/webmynd.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/webmynd.wordpress.com/119/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/webmynd.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/webmynd.wordpress.com/119/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/webmynd.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/webmynd.wordpress.com/119/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/webmynd.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/webmynd.wordpress.com/119/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/webmynd.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/webmynd.wordpress.com/119/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.webmynd.com&blog=2592024&post=119&subd=webmynd&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://blog.webmynd.com/2009/04/13/modularising-your-code-deployment/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/363e08c01d9caf37d45bf6e5a011421b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jamesbrady</media:title>
		</media:content>
	</item>
		<item>
		<title>How WebMynd decided to remove a feature – the ‘Ask Twitter’ case study</title>
		<link>http://blog.webmynd.com/2009/03/31/how-webmynd-decided-to-remove-a-feature-%e2%80%93-the-%e2%80%98ask-twitter%e2%80%99-case-study/</link>
		<comments>http://blog.webmynd.com/2009/03/31/how-webmynd-decided-to-remove-a-feature-%e2%80%93-the-%e2%80%98ask-twitter%e2%80%99-case-study/#comments</comments>
		<pubDate>Tue, 31 Mar 2009 19:15:22 +0000</pubDate>
		<dc:creator>WebMynd Team</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Product]]></category>

		<guid isPermaLink="false">http://blog.webmynd.com/?p=94</guid>
		<description><![CDATA[Last week we removed the &#8216;Ask Twitter&#8217; feature from WebMynd&#8217;s interface on search results pages. The idea of the feature was that, when you search, as well as being shown results from your favourite sources on the right-hand side of the results page, you could also ask your Twitter followers for help with your search.
It [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.webmynd.com&blog=2592024&post=94&subd=webmynd&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Last week we removed the &#8216;Ask Twitter&#8217; feature from WebMynd&#8217;s interface on search results pages. The idea of the feature was that, when you search, as well as being shown results from your favourite sources on the right-hand side of the results page, you could also ask your Twitter followers for help with your search.</p>
<p>It seemed to be an exciting idea when we first thought of it. By putting the ability to post to Twitter right into your search workflow, we thought to improve Twitter&#8217;s utility for you and make your search more social. Early beta testing by the WebMynd team seemed to validate this &#8211; I found a great fish and chip shop in Covent Garden, London by asking my Twitter network after I had searched unsuccessfully. It would never have occurred to me to ask had the interface not been right there on the search page.</p>
<p>We removed this feature last week and I&#8217;ll cover the reasons. It also got me thinking in more general terms about the circumstances under which you would consider removing a feature, since this isn&#8217;t the first time we&#8217;ve done it: in early versions of WebMynd last summer had a feature allowing offline access of your web history, and a feature which let you publish parts of your web history for the world to see as you browsed.</p>
<h4>The data looked bad</h4>
<p>We looked at how many unique users were posting to Twitter from our interface. For a start, this number was at most 10% of the total number of new signups that day. And while we did not break down our retention stats down to that level of granularity, the numbers were low enough that we could simply observe by the individual posts that very rarely did any user post more than once from the interface. The low proportion of new users trying it could be explained by the feature as it stood only being applicable to the overlap between Twitter users and WebMynd users. But the terrible retention was more worrying.</p>
<p>The fact that the data looked bad after a couple of months of tracking it was a great big warning light.  When thinking about the causes of the poor data, I asked myself the following questions:</p>
<h4>Did the feature satisfy the intended use case?</h4>
<p>While it allowed users to post a question to Twitter about their search query we had no built-in way to collate the answers. We assumed that the user, if already also a Twitter user, would have their own way to keep alerted on @replies or posts from people they followed, by for example, using <a href="//addons.mozilla.org/en-US/firefox/addon/5081">TwitterFox</a>. So we didn’t want to replicate those features in WebMynd and we had no automatic way to correlate replies to the question with the question itself.</p>
<p>Also, we observed that many of the users who did try out the feature appeared to be brand new Twitter users by the fact that their post from WebMynd was their first post. These users did not have many, if any followers, and probably had not yet figured out what set of habits and applications allowed them to keep track of replies.</p>
<p>So it seemed quite likely that the feature as it stood was not a complete enough solution.</p>
<h4>Did we promote the benefits sufficiently?</h4>
<p>We thought that putting the ‘Ask Twitter’ box onto our interface on Google and other major search engines would make it sufficiently high profile for a lot of our users to try out – our users saw that interface many times per day on average. But the data showed this wasn’t the case. We did not make a big splash on our website about the feature since we did not want to distract from our main use case with an experiment. We hoped that people would click on the ‘Ask Twitter’ link to open up the posting interface and so discover the feature and its usefulness.</p>
<p>It became clear to me that in order to really to a good test of the feature and use case, we would have to work much harder on promoting the benefits as well as making our implementation much more complete.</p>
<h4>Could a different feature satisfy the use case better?</h4>
<p>But that changed when we launched the WebMynd ‘Dock’ earlier this month. This allowed users to share links and post to Twitter as well as several other tools (Facebook, Delicious, Digg, Reddit, Hacker News) from a sidebar in the browser.</p>
<p>Within days of launching that feature, we had thousands of people actively using it, on average, 4 times per day. And while we had launched it for the purpose of sharing links as you browsed, it seemed so easy to also be able to make general posts to Twitter, including asking questions right from that interface.</p>
<p>For me that made the decision – we had another feature which satisfied the use case and more, where the data was showing great up-take by users. There seemed no sense in investing the effort to make the ‘Ask Twitter’ feature more complete and to promote that when the alternative feature was taking off so well.</p>
<h4>Did the intended use case exist?</h4>
<p>Ultimately it is possible that the ‘Ask Twitter’ feature was not well used simply because the use case simply didn’t exist. Maybe people don’t find the ability to easily ask their Twitter network questions related to their search useful. I don’t think the experiment we ran was sufficient to conclude that but it obviously was not working in the form we had originally tried.</p>
<h4>What now?</h4>
<p>It&#8217;s been about a week since we removed the feature, we have yet to receive a comment or complaint, and there have been no repercussions in terms of the usage of other features. So I think it is fair to conclude that it was the right choice. We should of course ask the <a href="http://www.toyota.co.jp/en/vision/traditions/mar_apr_06.html">5 whys</a> in our next product roadmap iteration to see what we can learn from the feature and how we might improve our decision making process.</p>
<p>We now have two interfaces into Twitter – the search widget that WebMynd puts on the right-hand side of Google and other search engines when the user selects it. And the Dock which allows users to post to Twitter and share links easily. I think those two features are just asking to be combined in new and interesting ways, and I very much doubt that the ‘Ask Twitter’ feature will our last experiment in this area.</p>
<p>In general, I don&#8217;t think we should be afraid of removing features, because if we cannot do that then we will become more reluctant to try out new ideas in the future and run the risk of them not working out. WebMynd did not start out embedding search results on the right-hand side of search engines. But when, almost in a whim, we just stuck some web history results up there to see what would happen, we discovered  the most popular feature in our product. It changed our direction as a company.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/webmynd.wordpress.com/94/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/webmynd.wordpress.com/94/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/webmynd.wordpress.com/94/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/webmynd.wordpress.com/94/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/webmynd.wordpress.com/94/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/webmynd.wordpress.com/94/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/webmynd.wordpress.com/94/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/webmynd.wordpress.com/94/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/webmynd.wordpress.com/94/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/webmynd.wordpress.com/94/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.webmynd.com&blog=2592024&post=94&subd=webmynd&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://blog.webmynd.com/2009/03/31/how-webmynd-decided-to-remove-a-feature-%e2%80%93-the-%e2%80%98ask-twitter%e2%80%99-case-study/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/79f2a102ffd970f2d4dfce0a6ba10671?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">WebMynd Team</media:title>
		</media:content>
	</item>
		<item>
		<title>Take control of your searching with the WebMynd browser extension for Firefox and Internet Explorer</title>
		<link>http://blog.webmynd.com/2009/03/01/take-control-of-your-searching-with-the-webmynd-browser-extension-for-firefox-and-internet-explorer/</link>
		<comments>http://blog.webmynd.com/2009/03/01/take-control-of-your-searching-with-the-webmynd-browser-extension-for-firefox-and-internet-explorer/#comments</comments>
		<pubDate>Sun, 01 Mar 2009 16:00:00 +0000</pubDate>
		<dc:creator>WebMynd Team</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.webmynd.com/?p=85</guid>
		<description><![CDATA[WebMynd helps you to find, and keep track of, information from sources you value most by personalizing the right-hand side of Google, Yahoo! and Live Search results pages. We&#8217;re launching a number of new features today &#8211; you can see a demo and download the latest version from webmynd.com.
Embed the sources you most value onto [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.webmynd.com&blog=2592024&post=85&subd=webmynd&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>WebMynd helps you to find, and keep track of, information from sources you value most by personalizing the right-hand side of Google, Yahoo! and Live Search results pages. We&#8217;re launching a number of new features today &#8211; you can see a demo and download the latest version from <a title="WebMynd Homepage" href="http://www.webmynd.com">webmynd.com</a>.</p>
<h4>Embed the sources you most value onto Google and other search engines<strong></strong></h4>
<p>WebMynd gets you to the information you need faster by letting you search multiple sources at once, and without needing to change your usual search engine. It also helps you filter the mass of information that is presented to you on a search engine, by grouping the search results by source &#8211; you usually know which sources you trust the most to give you the information you want for a particular type of search.</p>
<p>WebMynd now handles over 350K searches per day, personalizing the right-hand side of search engines by aggregating results from sources such as YouTube, Twitter, Wikipedia and Flickr. Since November this feature has been available on the Google results page for users of our Firefox browser extension. It is now available on Yahoo! and Live Search as well, on both Firefox and Internet Explorer.</p>
<p>You can try it out before you install on our <a title="WebMynd Demo" href="http://www.webmynd.com/demo?query=economy">demo page</a>.</p>
<h4>Keep track of what you&#8217;ve found and share it with friends</h4>
<p>Once you have search for and found the information you wanted, the last thing you want to do is search for it again when you next need it. Or look for it amongst hundreds of open tabs. Or have to copy and past a link into an email in order to share it with your friends and colleagues.</p>
<p>WebMynd has always allowed you to full-text search your history right on Google and browse your history as a film reel &#8211; like a DVR for the Web. And now WebMynd is launching the Dock &#8211; a sidebar that shows your recent history as a list and enables you to share the webpage you are on through email, Twitter, Facebook and other tools. This is the first of several social search and browsing features WebMynd will launch in the coming months.</p>
<h4>Publishers, other startups and Mozilla recommend WebMynd as a top search tool</h4>
<p>WebMynd is recommended by Mozilla and has built up a following of over 150K monthly users. Other startups and publishers value the opportunity to include their search results as a WebMynd source. A number of them, including <a title="Fluther" href="http://fluther.com">Fluther</a>, <a title="OneRiot" href="http://www.oneriot.com/product/addons">OneRiot</a> and <a title="Hacker News" href="http://news.ycombinator.com">Hacker News</a> are distributing customized versions of WebMynd which show their results on the right-hand side by default as well as allowing all WebMynd users to add their content. WebMynd has custom versions of its search personalization available for major publishers such as <a title="ForbesSearch powered by WebMynd" href="http://www.webmynd.com/html/forbes.html">Forbes</a>, <a title="LATimesSearch powered by WebMynd" href="http://www.webmynd.com/html/latimes.html">LA Times</a>, <a title="CNNSearch powered by WebMynd" href="http://www.webmynd.com/html/cnn.html">CNN</a>, <a title="DaylifeSearch powered by WebMynd" href="http://www.webmynd.com/html/daylife.html">Daylife</a> and <a title="TechCrunchSearch powered by WebMynd" href="http://www.webmynd.com/html/techcrunch.html">TechCrunch</a>.</p>
<p>If you&#8217;re a publisher and think your users would value being able to access your branding content whenever they search, then please <a title="Email WebMynd" href="mailto:founders@webmynd.com">get in touch</a>.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/webmynd.wordpress.com/85/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/webmynd.wordpress.com/85/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/webmynd.wordpress.com/85/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/webmynd.wordpress.com/85/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/webmynd.wordpress.com/85/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/webmynd.wordpress.com/85/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/webmynd.wordpress.com/85/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/webmynd.wordpress.com/85/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/webmynd.wordpress.com/85/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/webmynd.wordpress.com/85/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.webmynd.com&blog=2592024&post=85&subd=webmynd&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://blog.webmynd.com/2009/03/01/take-control-of-your-searching-with-the-webmynd-browser-extension-for-firefox-and-internet-explorer/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/79f2a102ffd970f2d4dfce0a6ba10671?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">WebMynd Team</media:title>
		</media:content>
	</item>
		<item>
		<title>Databases as a service: FathomDB</title>
		<link>http://blog.webmynd.com/2009/02/28/databases-as-a-service-fathomdb/</link>
		<comments>http://blog.webmynd.com/2009/02/28/databases-as-a-service-fathomdb/#comments</comments>
		<pubDate>Sat, 28 Feb 2009 09:42:41 +0000</pubDate>
		<dc:creator>James Brady</dc:creator>
				<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://blog.webmynd.com/?p=75</guid>
		<description><![CDATA[I don&#8217;t think Google want to use BigTable. I think Google have to use BigTable because of the absurd scale that they&#8217;re working at.
Unstructured databases (like Amazon&#8217;s SimpleDB and Google&#8217;s Data Store &#8211; built on BigTable) are great in that they are easy to scale, have an uncomplicated model of how data is stored in [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.webmynd.com&blog=2592024&post=75&subd=webmynd&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>I don&#8217;t think Google want to use <a href="http://labs.google.com/papers/bigtable.html">BigTable</a>. I think Google have to use BigTable because of the absurd scale that they&#8217;re working at.</p>
<p>Unstructured databases (like Amazon&#8217;s <a href="http://aws.amazon.com/simpledb/">SimpleDB</a> and Google&#8217;s <a href="http://code.google.com/appengine/docs/python/gettingstarted/usingdatastore.html">Data Store</a> &#8211; built on BigTable) are great in that they are easy to scale, have an uncomplicated model of how data is stored in them and a simple approach to how that data is queried. These shortcuts and simplifications on the data storage and retrieval are key to the scalability of the databases. The databases have basically been reduced down to being huge distributed hash tables.</p>
<h4>Unstructured databases: the downside</h4>
<p>Unfortunately, the same simplifications that enable enormous scalability are very punitive in the restrictions they place on us as programmers. When we think about modeling our data, we think that a user HAS-MANY, a manager IS-A employee, a blog comment BELONGS-TO a blog post, and so on. Those relationships are just not representable in unstructured databases; you have to synthesise them yourself in software.</p>
<p>These connections between objects are not merely the result of us all having been conditioned to &#8220;think in SQL&#8221; over the last 35 years. Rather, these are the real relationships between the actual objects we&#8217;re modelling; it was SQL that was designed so that it matched reality, not the other way round.</p>
<p>Your average small to medium startup company does not need to store the entire internet in a database, so unstructured databases burden us with unneeded, inconvenient over-simplifications. As Einstein said:</p>
<blockquote><p>Things should be as simple as possible, but not simpler.</p></blockquote>
<h4>Unstructured databases: the upside</h4>
<p>And yet there is a proto-trend towards using these unstructured databases. The reason is that they are much, <em>much</em> more easy to offer &#8220;as a service&#8221;, and having someone else managed your database makes a lot sense to startups. Database maintenance is a huge time sink, and small companies should strive to spend as much time as possible on differentiating features and as little time as possible on mundane admin tasks and overhead.</p>
<p>That SimpleDB and Data Store liberates you from the need to be a DBA is a big enough draw for a lot of people to live with the downsides that the unstructured product brings. You don&#8217;t need to configure backups, implement master / slave replication, tweak performance parameters, set up sharding &#8211; the list goes on and on. The surfeit of &#8220;how do I set up replication&#8221; questions on MySQL forums are a testament to how easy <em>that</em> is for the inexperienced.</p>
<p>Surely, then, the ideal situation would be a pay-as-you-go, managed database provider with true relational capabilities? <a href="http://webmynd.com">WebMynd</a> have been lucky enough to be using just such a database over the last year: <a href="http://fathomdb.com/">FathomDB</a>, which launches in private beta today.</p>
<h4><a href="http://fathomdb.com/">FathomDB</a>: relational <em>and</em> managed</h4>
<p>To us, FathomDB just looks like a normal MySQL database. There&#8217;s no time wasted figuring out how to convert your data model into a denormalised form, and existing databases can be easily converted to run FathomDB.</p>
<p>However, that normal-looking MySQL database is fully managed, so that we don&#8217;t have to worry about backups, monitoring, replication: the very same things that SimpleDB and Data Store relieve you from worrying about.</p>
<p>The time savings have been huge. On the backend, we&#8217;ve been able to spend our time working on new search technology without having to worry about database admin tasks at the same time. We&#8217;ve been able to focus on valuable features, relevant to our business and company, and been liberated from spending time playing the DBA.</p>
<h4>Scaling</h4>
<p>As we&#8217;ve grown over the last few months, FathomDB have used us a proving tool for their scalability, and are now inserting 5 million new rows every day; that&#8217;s 60 rows per second on average, although we spike up to around 100 per second. For comparison, there are 2.8 million documents, total, in the English Wikipedia: being able to handle this scale should be more than sufficient for the vast majority of startups.</p>
<p><a href="http://fathomdb.com/">FathomDB</a> bills itself as &#8220;databases as a service&#8221;. The difference with them compared to databases like SimpleDB and Data Store is that is really <strong>is</strong> a database. All the features of RDBMSes that you know and want are available, with the added benefit of a pay-as-you-go pricing model and a fully managed service.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/webmynd.wordpress.com/75/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/webmynd.wordpress.com/75/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/webmynd.wordpress.com/75/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/webmynd.wordpress.com/75/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/webmynd.wordpress.com/75/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/webmynd.wordpress.com/75/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/webmynd.wordpress.com/75/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/webmynd.wordpress.com/75/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/webmynd.wordpress.com/75/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/webmynd.wordpress.com/75/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.webmynd.com&blog=2592024&post=75&subd=webmynd&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://blog.webmynd.com/2009/02/28/databases-as-a-service-fathomdb/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/363e08c01d9caf37d45bf6e5a011421b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jamesbrady</media:title>
		</media:content>
	</item>
		<item>
		<title>Mocking objects in Python unit tests</title>
		<link>http://blog.webmynd.com/2009/02/18/mocking-objects-in-python-unit-tests/</link>
		<comments>http://blog.webmynd.com/2009/02/18/mocking-objects-in-python-unit-tests/#comments</comments>
		<pubDate>Wed, 18 Feb 2009 06:42:05 +0000</pubDate>
		<dc:creator>James Brady</dc:creator>
				<category><![CDATA[technical]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[minimock]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[unit test]]></category>

		<guid isPermaLink="false">http://webmynd.wordpress.com/?p=59</guid>
		<description><![CDATA[The seamless integration of doctest, Nose, Sphinx and MiniMock makes writing good doc strings extremely useful in Python. Why can't we use MiniMock in unit tests too?<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.webmynd.com&blog=2592024&post=59&subd=webmynd&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>The seamless integration of <a href="http://docs.python.org/library/doctest.html#module-doctest">doctest</a>, <a href="http://somethingaboutorange.com/mrl/projects/nose/">Nose</a>, <a href="http://sphinx.pocoo.org/">Sphinx</a> and <a href="http://pypi.python.org/pypi/MiniMock/">MiniMock</a> means that taking a little more time to write your Python doc strings can give you testable documentation, full of examples, in HTML or LaTeX markup, and main-line unit test coverage &#8220;for free&#8221;.</p>
<p>The <em>bon mariage</em> between these agile tools has worked so well for us that when it came to extending test coverage up to 100% using a full Nose test suite, we were really pining for the painless mock objects that MiniMock gives you.</p>
<p>MiniMock works by printing out your code&#8217;s actual usage of mock objects so that it can be compared with the expected usage you specify in the doc string. For example, this function reads a URL and writes it to a file-like object:</p>
<pre>import urllib
def write_url(url, out_file):
    """
    Example::

        &gt;&gt;&gt; from minimock import mock, Mock
        &gt;&gt;&gt; mock('urllib.urlopen', returns=Mock('urlopen_result'))
        &gt;&gt;&gt; write_url('http://webmynd.com', Mock('out_file'))      #doctest: +ELLIPSIS
        Called urllib.urlopen('http://webmynd.com')
        Called urlopen_result.read()
        Called out_file.write(None)
        &lt;Mock ... out_file&gt;
    """
    page_content = urllib.urlopen(url)
    out_file.write(page_content.read())
    return out_file</pre>
<p>The supplied doctest shows a couple of different mocking methods, and also doctest&#8217;s invaluable ELLIPSIS option, which allows for fuzzy matching of the expected output.</p>
<p>When writing unit tests for this method, rather than a single simple doctest, there are two problems.</p>
<ol>
<li>there&#8217;s no convenient way to track the usage of MiniMock-ed objects</li>
<li>the fuzzy matching tools in doctest aren&#8217;t particularly conveniently exposed for unit test usage</li>
</ol>
<h2>Tracking MiniMock usage</h2>
<p>To track the usage of mocked objects, we subclass minimock.Printer to store the console output in a StringIO object, rather than printing it to sys.stdout:</p>
<pre>class TraceTracker(Printer):
    def __init__(self, *args, **kw):
        self.out = StringIO()
        super(TraceTracker, self).__init__(self.out, *args, **kw)
        self.checker = doctest.OutputChecker()
        self.options =  doctest.ELLIPSIS
        self.options |= doctest.NORMALIZE_WHITESPACE
        self.options |= doctest.REPORT_UDIFF

    def check(self, want):
        return self.checker.check_output(want, self.dump(),
            optionflags=self.options)

    def diff(self, want):
        return self.checker.output_difference(doctest.Example("", want),
            self.dump(), optionflags=self.options)

    def dump(self):
        return self.out.getvalue()</pre>
<p>The check() method uses doctest&#8217;s OutputChecker to compare the observed and expected mock usage, while diff() returns a human-readable comparison of the observed and expected mock usage.</p>
<p>The basic idea is to store up the messages MiniMock <em>would</em> have printed in a convenient container, and provide some utilities to interrogate those messages.</p>
<h2>Matching MiniMock usage</h2>
<p>The TraceTracker class shown above already gives us all the functionality we need &#8211; all that is required is a convenient utility function:</p>
<pre>def assert_same_trace(tracker, want):
    assert tracker.check(want), tracker.diff(want)</pre>
<p>This function allows us to check the mock objects are being used as we expected, and prints out a human-readable diff of the expected and observed usage if applicable.</p>
<h2>Usage Example</h2>
<p>As a concrete example, I&#8217;ll convert the doctest for the write_url function to a Nose-style unit test:</p>
<pre>def test_write_url():
    tt = TraceTracker()
    mock('urllib.urlopen', returns=Mock('urlopen_result', tracker=tt), tracker=tt)
    write_url('http://webmynd.com', Mock('out_file', tracker=tt))

    expected_output = """Called urllib.urlopen('http://webmynd.com')
Called urlopen_result.read()
Called out_file.write(None)"""
    assert_same_trace(tt, expected_output)</pre>
<p>The definition of the expected MiniMock usage (called expected_output here) can feel a little clunky, but in our experience, these definitions are quite often common between test cases, so can be defined once and shared.</p>
<p>MiniMock is great for quickly faking out fairly complex external dependencies, with little, if any, compromise on the rigour of your tests. By adapting its usage for unit tests, as described here, you can have all that convenience and power in your more exhaustive test suites.</p>
<p>The code given above is available as <a href="http://pypi.python.org/pypi/MiniMockUnit/">MiniMockUnit</a> on PyPI.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/webmynd.wordpress.com/59/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/webmynd.wordpress.com/59/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/webmynd.wordpress.com/59/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/webmynd.wordpress.com/59/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/webmynd.wordpress.com/59/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/webmynd.wordpress.com/59/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/webmynd.wordpress.com/59/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/webmynd.wordpress.com/59/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/webmynd.wordpress.com/59/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/webmynd.wordpress.com/59/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.webmynd.com&blog=2592024&post=59&subd=webmynd&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://blog.webmynd.com/2009/02/18/mocking-objects-in-python-unit-tests/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/363e08c01d9caf37d45bf6e5a011421b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jamesbrady</media:title>
		</media:content>
	</item>
	</channel>
</rss>