<?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:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Fetchez le Python</title>
	<atom:link href="http://tarekziade.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://tarekziade.wordpress.com</link>
	<description>Technical blog on the Python programming language, in a pure Frenglish style. Main topics are Python and Mozilla - This blog does not engage my employer</description>
	<lastBuildDate>Sat, 28 Jan 2012 09:58:34 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='tarekziade.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://1.gravatar.com/blavatar/107485281a5c5ceea5df5c78be3fd0d5?s=96&#038;d=http%3A%2F%2Fs2.wp.com%2Fi%2Fbuttonw-com.png</url>
		<title>Fetchez le Python</title>
		<link>http://tarekziade.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://tarekziade.wordpress.com/osd.xml" title="Fetchez le Python" />
	<atom:link rel='hub' href='http://tarekziade.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Mozillians, win a free pass for Pycon US &#8211; take 2</title>
		<link>http://tarekziade.wordpress.com/2012/01/04/mozillians-win-a-free-pass-for-pycon-us-take-2/</link>
		<comments>http://tarekziade.wordpress.com/2012/01/04/mozillians-win-a-free-pass-for-pycon-us-take-2/#comments</comments>
		<pubDate>Wed, 04 Jan 2012 22:41:43 +0000</pubDate>
		<dc:creator>Tarek Ziadé</dc:creator>
				<category><![CDATA[mozilla]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://tarekziade.wordpress.com/?p=2302</guid>
		<description><![CDATA[I am extending the contest until Feb the 1st &#8211; Mozillians, win a free pass for Pycon US Filed under: mozilla, python<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tarekziade.wordpress.com&amp;blog=448161&amp;post=2302&amp;subd=tarekziade&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I am extending the contest until Feb the 1st &#8211; <a href="https://tarekziade.wordpress.com/2011/10/13/mozillians-win-a-free-pass-for-pycon-us/">Mozillians, win a free pass for Pycon US</a></p>
<br />Filed under: <a href='http://tarekziade.wordpress.com/category/mozilla/'>mozilla</a>, <a href='http://tarekziade.wordpress.com/category/python/'>python</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/tarekziade.wordpress.com/2302/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/tarekziade.wordpress.com/2302/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/tarekziade.wordpress.com/2302/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/tarekziade.wordpress.com/2302/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/tarekziade.wordpress.com/2302/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/tarekziade.wordpress.com/2302/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/tarekziade.wordpress.com/2302/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/tarekziade.wordpress.com/2302/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/tarekziade.wordpress.com/2302/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/tarekziade.wordpress.com/2302/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/tarekziade.wordpress.com/2302/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/tarekziade.wordpress.com/2302/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/tarekziade.wordpress.com/2302/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/tarekziade.wordpress.com/2302/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tarekziade.wordpress.com&amp;blog=448161&amp;post=2302&amp;subd=tarekziade&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://tarekziade.wordpress.com/2012/01/04/mozillians-win-a-free-pass-for-pycon-us-take-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5e5142d6a1a578f02e2d94c4d6d31088?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">tarek</media:title>
		</media:content>
	</item>
		<item>
		<title>The fear of CRUD</title>
		<link>http://tarekziade.wordpress.com/2012/01/03/the-fear-of-crud/</link>
		<comments>http://tarekziade.wordpress.com/2012/01/03/the-fear-of-crud/#comments</comments>
		<pubDate>Mon, 02 Jan 2012 23:17:09 +0000</pubDate>
		<dc:creator>Tarek Ziadé</dc:creator>
				<category><![CDATA[mozilla]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://tarekziade.wordpress.com/?p=2279</guid>
		<description><![CDATA[Cornice is growing steadily, and we are thinking about the different ways to use it for our needs. One use case that comes often when we build web services is the need to publish a SQL Database via HTTP. For instance, in a project I am working on, we might expose a list of servers [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tarekziade.wordpress.com&amp;blog=448161&amp;post=2279&amp;subd=tarekziade&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://packages.python.org/cornice/">Cornice</a> is growing steadily, and we are thinking about the different ways to use it for our needs. One use case that comes often when we build web services is the need to publish a SQL Database via HTTP.</p>
<p>For instance, in a project I am working on, we might expose a list of servers and some information about them, that are stored in a SQL DB . The goal is to allow some management scripts to interact with the DB, to set and retrieve information about the servers, like: &#8220;can I use <em>server 12</em> as a node for <em>application X</em> ?&#8221;</p>
<p>Interacting with CURL or a similar tool is simpler and more portable than coding yet another SQL client for this, so the idea is to see how this kind of web service can be done is the minimum pain with Cornice.</p>
<p>What I am thinking about building is a small <a href="https://en.wikipedia.org/wiki/Create,_read,_update_and_delete">CRUD</a> interface that glues Cornice and SQLAlchemy. The latter has a way to define a database schema explicitly via <a href="http://www.sqlalchemy.org/docs/orm/mapper_config.html"><em>mappings</em></a> meaning that it&#8217;s easy to write a generic layer that exposes the database to the web via Cornice definitions. The work consists of transforming POST &amp; PUT requests that contains data to write to the DB into SQLAlchemy objects, and transforming select results asked via GET requests into the proper responses.</p>
<p>Nothing very new, there are tons of existing systems that implement CRUD on the top of <a href="https://en.wikipedia.org/wiki/Object-Relational_Mapping">ORMs</a> or plain SQL libraries. The only reason to build yet another one is to use it in the context of our current toolset which is composed of Cornice, Pyramid &amp; SQLAlchemy for most projects. The whole code will probably be less than 300 lines at the end anyways.</p>
<p><em><strong>Oh my</strong>.</em></p>
<p>Turns out this idea is really freaking out some people around me. There&#8217;s a strong aversion of some coders against anything that looks a bit like <a href="https://en.wikipedia.org/wiki/Active_record">Active Records</a> &#8212; in the Rails Context. In other words anything that would completely automate the serialization &amp; deserialization layer and make it hard to tweak some code.</p>
<p>Another criticism is that a CRUD system would not be able to scale in the context of a big database, like Firefox Sync, that uses numerous databases to shard data.</p>
<p>Turns out building a CRUD on tools like SQLAlchemy or Pyramid is not really going to ruin your scalability as long as:</p>
<ul>
<li>you can tweak the serialization / deserialization</li>
<li>you can override any operation in the CRUD operations when needed</li>
<li>you don&#8217;t shoot yourself in the foot by using CRUD with some code or DB that is not meant to be used that way</li>
<li>you can use the power of the underlying tools without being blocked by the lib</li>
</ul>
<p>For the latter, Ben Bangert was pointing me at <a href="http://www.sqlalchemy.org/docs/orm/extensions/horizontal_shard.html">SQLAlchemy horizontal feature</a>, which is basically what I wrote from scratch last year to make the Sync server shard across databases&#8230; At this point I sense that Firefox Sync could have been built with a CRUD lib, and be as efficient as it is today, because when I look at the queries produced by the code and the one a CRUD lib would produce, we are one or two tweaks away.</p>
<p>Anyways, here&#8217;s a first attempt at such a library.</p>
<h3>Defining the model</h3>
<p>In SQLAlchemy, you can define the DB model using mappings, which are simple classes containing a description of the tables.</p>
<p>For example, if I have a class &#8220;users&#8221; with a field &#8220;id&#8221; and a field &#8220;name&#8221;, the mapping will look like this:</p>
<pre>class Users(_Base):                                           
    __tablename__ = 'users'                                      
    id = Column(Integer, primary_key=True)                    
    name = Column(String(256), nullable=False)</pre>
<p>What I started to do is write a meta class one can use in a class to publish the mapping via HTTP.</p>
<p>Here&#8217;s an example:</p>
<pre>from cornicesqla import MetaDBView
from myapp import Users, DBSession

class UsersView(object):
    __metaclass__ = MetaDBView
    mapping = Users
    path = '/users/{id}'
    collection_path = '/users'
    session = DBSession</pre>
<p>What we have here is the definition of a view for the Users mapping. The class defines an URI for the collection (collection_path) and for each user (path). The session attribute is an SQLAlchemy <a href="http://www.sqlalchemy.org/docs/orm/session.html">session</a> object you usually define when you work with that tool.</p>
<p>That&#8217;s it.</p>
<p>The model gets published, and you can GET, PUT, POST and DELETE on <em>/users</em> and <em>/users/someid.</em></p>
<p>The code of the prototype is <a href="https://github.com/mozilla-services/cornice-sqla/blob/master/cornicesqla/views.py">here</a> and you can find <a href="https://github.com/mozilla-services/cornice-sqla/tree/master/cornicesqla/tests">a working example in the tests here</a>. It&#8217;s called <strong>cornice-sqla</strong></p>
<h3>Tweaking serialization &amp; data validation</h3>
<p>By default, <em>cornice-sqla</em> will serialize and deserialize using JSON but you can tweak these steps by providing a custom serializer, or deserializer (or both.)</p>
<p>Let&#8217;s say you want to use the <a href="http://docs.pylonsproject.org/projects/colander/en/latest/">Colander libary</a> to validate and serialize the data. To do this, you just have to write your serializer method into the view class</p>
<pre>class UsersValidation(colander.MappingSchema):
    name = colander.SchemaNode(colander.String())

class UsersView(object):
    __metaclass__ = MetaDBView

    mapping = Users
    path = '/users/{id}'
    collection_path = '/users'
    session = DBSession

    def serialize(self):
        """Unserialize the data from the request, to serialize it for the DB"""
        try:
            user = json.loads(self.request.body)
        except ValueError:
            request.errors.add('body', 'item', 'Bad Json data!')
            # let's quit
            return

        schema = UsersValidation()
        try:
            deserialized = schema.deserialize(user)
        except Invalid, e:
            # the struct is invalid
            request.errors.add('body', 'item', e.message)

        return deserialized</pre>
<p>Colander is used here to validate the incoming request and create a flat mapping we can push into the DB. Cornice&#8217;s error system is in usage here, as explained <a href="http://packages.python.org/cornice/validation.html">here</a>.</p>
<p>You can tweak the data that gets back from the DB with <em><strong>unserialize()</strong></em>, and for the collection URI, use <em><strong>collection_serialize()</strong></em> and <em><strong>collection_unserialize()</strong></em>.</p>
<h3>Tweaking C, R, U or D</h3>
<p>cornice-sqla is based on a fresh feature Gael added into Cornice lately: <a href="https://github.com/mozilla-services/cornice/blob/master/docs/source/resources.rst">resources</a>. A resource is a class where you can define <em>get()</em>, <em>post()</em>, <em>delete()</em> and <em>put()</em> methods for a given URI.</p>
<p>cornice-sqla views are based on resources, meaning that you can override anyone of those methods and do whatever you want if you don&#8217;t want the CRUD part.</p>
<h3>What&#8217;s next</h3>
<p>I need to make sure everything you can do in Cornice (acls various options etc) can still be done in cornice-sqla, and start to work with more complex DB schema that include relations etc.  I also need to add basic missing features like batching and some docs.</p>
<p>My hope at the end is that this small library will reduce considerably the code needed in some of our projects that interact with SQL.</p>
<br />Filed under: <a href='http://tarekziade.wordpress.com/category/mozilla/'>mozilla</a>, <a href='http://tarekziade.wordpress.com/category/python/'>python</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/tarekziade.wordpress.com/2279/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/tarekziade.wordpress.com/2279/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/tarekziade.wordpress.com/2279/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/tarekziade.wordpress.com/2279/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/tarekziade.wordpress.com/2279/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/tarekziade.wordpress.com/2279/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/tarekziade.wordpress.com/2279/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/tarekziade.wordpress.com/2279/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/tarekziade.wordpress.com/2279/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/tarekziade.wordpress.com/2279/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/tarekziade.wordpress.com/2279/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/tarekziade.wordpress.com/2279/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/tarekziade.wordpress.com/2279/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/tarekziade.wordpress.com/2279/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tarekziade.wordpress.com&amp;blog=448161&amp;post=2279&amp;subd=tarekziade&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://tarekziade.wordpress.com/2012/01/03/the-fear-of-crud/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5e5142d6a1a578f02e2d94c4d6d31088?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">tarek</media:title>
		</media:content>
	</item>
		<item>
		<title>Pyramid @ Python 3</title>
		<link>http://tarekziade.wordpress.com/2011/12/25/pyramid-python-3/</link>
		<comments>http://tarekziade.wordpress.com/2011/12/25/pyramid-python-3/#comments</comments>
		<pubDate>Sun, 25 Dec 2011 10:15:43 +0000</pubDate>
		<dc:creator>Tarek Ziadé</dc:creator>
				<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://tarekziade.wordpress.com/?p=2272</guid>
		<description><![CDATA[If you have been following closely the latest work done by Chris on WebOb, you know that WebOb and eventually Pyramid became Python 3 compatible. That makes Python 3 a very tempting target for a new web project. Paste &#38; PasteScript still need to be ported to Python 3 and the Pyramid team has chosen [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tarekziade.wordpress.com&amp;blog=448161&amp;post=2272&amp;subd=tarekziade&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>If you have been following closely the latest work done by Chris on WebOb, you know that WebOb and eventually Pyramid became Python 3 compatible.</p>
<p>That makes Python 3 a very tempting target for a new web project.</p>
<p>Paste &amp; PasteScript still need to be ported to Python 3 and the Pyramid team has chosen not to. They have created their own paster replacer instead, which can be used to initiate a Pyramid project or run the app using the <em>.ini</em> file.</p>
<p>I am wondering if it would not be simpler at this point to drop Paste and use this replacer for all Python 3 frameworks that are using the Paste script and templates features.</p>
<p>Besides all the features Pyramid and its libs turns out most of the libs you usually need to build a classical web app already support Python 3, like SQLALchemy and PyMysql for MySQL access, Pylibmc for Memcached;</p>
<p>Things I am still missing in Python 3:</p>
<ul>
<li>gevent</li>
<li>gunicorn</li>
<li>python-ldap</li>
<li>Cornice &#8212; I will port it soon</li>
</ul>
<p>If you want to give it a shot, get the latest Python 3.2 and grab more details at :<a href="https://github.com/Pylons/pyramid/wiki/Python-3-Porting"> https://github.com/Pylons/pyramid/wiki/Python-3-Porting</a></p>
<p>And if you miss one lib, <a href="https://plus.google.com/u/1/106436370949746015255/posts/SAwkyVyUhWV">add it here</a></p>
<p>Merry Christmas !</p>
<br />Filed under: <a href='http://tarekziade.wordpress.com/category/python/'>python</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/tarekziade.wordpress.com/2272/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/tarekziade.wordpress.com/2272/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/tarekziade.wordpress.com/2272/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/tarekziade.wordpress.com/2272/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/tarekziade.wordpress.com/2272/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/tarekziade.wordpress.com/2272/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/tarekziade.wordpress.com/2272/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/tarekziade.wordpress.com/2272/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/tarekziade.wordpress.com/2272/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/tarekziade.wordpress.com/2272/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/tarekziade.wordpress.com/2272/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/tarekziade.wordpress.com/2272/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/tarekziade.wordpress.com/2272/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/tarekziade.wordpress.com/2272/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tarekziade.wordpress.com&amp;blog=448161&amp;post=2272&amp;subd=tarekziade&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://tarekziade.wordpress.com/2011/12/25/pyramid-python-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5e5142d6a1a578f02e2d94c4d6d31088?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">tarek</media:title>
		</media:content>
	</item>
		<item>
		<title>Tutorial &#8211; build your web services with Cornice</title>
		<link>http://tarekziade.wordpress.com/2011/12/21/tutorial-build-your-web-services-with-cornice/</link>
		<comments>http://tarekziade.wordpress.com/2011/12/21/tutorial-build-your-web-services-with-cornice/#comments</comments>
		<pubDate>Wed, 21 Dec 2011 10:50:07 +0000</pubDate>
		<dc:creator>Tarek Ziadé</dc:creator>
				<category><![CDATA[mozilla]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://tarekziade.wordpress.com/?p=2258</guid>
		<description><![CDATA[At this stage, I think we&#8217;ve added enough helpers in Cornice to get anyone started in building web services in Python. As a reminder, Cornice provides helpers to build &#38; document REST-ish Web Services with Pyramid, a Python web framework. The main benefits of Cornice are: automatic handling of some HTTP errors &#8211; Ask yourself: [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tarekziade.wordpress.com&amp;blog=448161&amp;post=2258&amp;subd=tarekziade&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>At this stage, I think we&#8217;ve added enough helpers in Cornice to get anyone started in building web services in Python.</p>
<p>As a reminder, Cornice provides helpers to build &amp; document REST-ish Web Services with Pyramid, a Python web framework. The main benefits of Cornice are:</p>
<ul>
<li>automatic handling of some HTTP errors &#8211; Ask yourself: is your app handling properly 405 or 406 errors?</li>
<li>automatic web service documentation via a Sphinx extension.</li>
<li>a simple way to validate and convert requests data, and return structured 400 responses.</li>
</ul>
<p>This is a small tutorial, extracted from our documentation.</p>
<p>Let’s create a full working application with <strong>Cornice</strong>. We want to create a light messaging service.</p>
<p>You can find its whole source code at <a href="https://github.com/mozilla-services/cornice/blob/master/examples/messaging">https://github.com/mozilla-services/cornice/blob/master/examples/messaging</a></p>
<p>Features:</p>
<ul>
<li>users can register to the service</li>
<li>users can list all registered users</li>
<li>users can send messages</li>
<li>users can retrieve the latest messages</li>
<li>messages have three fields: sender, content, color (red or black)</li>
<li>adding a message is done through authentication</li>
</ul>
<p>Limitations:</p>
<ul>
<li>there’s a single channel for all messages.</li>
<li>if a user with the same name is already registered, he cannot register.</li>
<li>all messages and users are kept in memory.</li>
</ul>
<div id="design">
<h2>Design</h2>
<p>The application provides two services:</p>
<ul>
<li><strong>users</strong>, at <strong>/users</strong>: where you can list all users or register a new one</li>
<li><strong>messages</strong>, at <strong>/</strong>: where you can read the messages or add new ones</li>
</ul>
<p>On the server, the data is kept in memory.</p>
<p>We’ll provide a single CLI client in Python, using Curses.</p>
</div>
<div id="setting-up-the-development-environment">
<h2>Setting up the development environment</h2>
<p>To create this application, we’ll use Python 2.7. Make sure you have it on your system, then install <strong>virtualenv</strong> (see <a href="http://pypi.python.org/pypi/virtualenv">http://pypi.python.org/pypi/virtualenv</a>.)</p>
<p>Create a new directory and a virtualenv in it:</p>
<div>
<pre>$ mkdir messaging
$ cd messaging
$ virtualenv --no-site packages .</pre>
</div>
<p>Once you have it, install Cornice in it with Pip:</p>
<div>
<pre>$ bin/pip install Cornice</pre>
</div>
<p>Cornice provides a Paster Template you can use to create a new application:</p>
<div>
<pre>$ bin/paster create -t cornice messaging
Selected and implied templates:
cornice#cornice  A Cornice application

Variables:
egg:      messaging
package:  messaging
project:  messaging
Enter appname (Application name) ['']: Messaging
Enter description (One-line description of the project) ['']: A simple messaging service.
Enter author (Author name) ['']: Tarek
Creating template cornice
...
Generating Application...
Running python2.7 setup.py egg_info</pre>
</div>
<p>Once your application is generated, go there and call <em>develop</em> against it:</p>
<div>
<pre>$ cd messaging
$ ../bin/python setup.py develop
...</pre>
</div>
<p>The application can now be launched via Paster, it provides a default “Hello” service, you can check:</p>
<div>
<pre>$ ../bin/paster serve messaging.ini
Starting server in PID 7618.
serving on 0.0.0.0:5000 view at http://127.0.0.1:5000</pre>
</div>
<p>Once the application is running, visit <a href="http://127.0.0.1:5000/">http://127.0.0.1:5000</a> in your browser or Curl and make sure you get:</p>
<div>
<div>
<pre>{'Hello': 'World'}</pre>
</div>
</div>
</div>
<div id="defining-the-services">
<h2>Defining the services</h2>
<p>Let’s open the file in messaging/views.py, it contains all the Services:</p>
<div>
<div>
<pre>from cornice import Service

hello = Service(name='hello', path='/', description="Simplest app")

@hello.get()
def get_info(request):
    """Returns Hello in JSON."""
    return {'Hello': 'World'}</pre>
</div>
</div>
<div id="users-managment">
<h3>Users managment</h3>
<p>We’re going to get rid of the Hello service, and change this file in order to add our first service &#8211; the users managment</p>
<div>
<div>
<pre>
_USERS = {}

users = Service(name='users', path='/users', description="Users"0

@users.get(validator=valid_token)
def get_users(request):
    """Returns a list of all users."""
    return {'users': _USERS.keys()}

@users.put(validator=unique)
def create_user(request):
    """Adds a new user."""
    user = request.validated['user']
    _USERS[user['name']] = user['token']
    return {'token': '%s-%s' % (user['name'], user['token'])}

@users.delete(validator=valid_token)
def del_user(request):
    """Removes the user."""
    user = request.validated['user']
    del _USERS[user['name']]
    return {'goodbye': user['name']}
</pre>
</div>
</div>
<p>What we have here is 3 methods on <strong>/users</strong>:</p>
<ul>
<li><strong>GET</strong>: simply return the list of users names – the keys of _USERS</li>
<li><strong>PUT</strong>: adds a new user and returns a unique token</li>
<li><strong>DELETE</strong>: removes the user.</li>
</ul>
<p>Remarks:</p>
<ul>
<li><strong>PUT</strong> uses the <strong>unique</strong> validator to make sure that the user name is not already taken. That validator is also in charge of generating a unique token associated with the user.</li>
<li><strong>GET</strong> users the <strong>valid_token</strong> to verify that a <strong>X-Messaging-Token</strong> header is provided in the request, with a valid token. That also identifies the user.</li>
<li><strong>DELETE</strong> also identifies the user then removes it.</li>
</ul>
<p>Validators are filling the <strong>request.validated</strong> mapping, the service can then use.</p>
<p>Here’s their code:</p>
<div>
<div>
<pre>import os
import binascii
from webob import exc

def _create_token():
    return binascii.b2a_hex(os.urandom(20))

def valid_token(request):
    header = 'X-Messaging-Token'

    token = request.headers.get(header)
    if token is None:
        raise exc.HTTPUnauthorized()

    token = token.split('-')
    if len(token) != 2:
        raise exc.HTTPUnauthorized()

    user, token = token

    valid = user in _USERS and _USERS[user] == token
    if not valid:
        raise exc.HTTPUnauthorized()

    request.validated['user'] = user

def unique(request):
    name = request.body
    if name in _USERS:
        request.errors.add('url', 'name', 'This user exists!')
    else:
        user = {'name': name, 'token': _create_token()}
        request.validated['user'] = user</pre>
</div>
</div>
<p>When the validator finds errors, it adds them to the <strong>request.errors</strong> mapping, and that will return a 400 with the errors.</p>
<p>Let’s try our application so far with CURL:</p>
<div>
<pre>$ curl http://localhost:5000/users
{"status": "error", "errors": [{"location": "header",
                                "name": "X-Messaging-Token",
                                "description": "No token"}]}

$ curl -X PUT http://localhost:5000/users -d 'tarek'
{"token": "tarek-a15fa2ea620aac8aad3e1b97a64200ed77dc7524"}

$ curl http://localhost:5000/users -H "X-Messaging-Token:tarek-a15fa2ea620aac8aad3e1b97a64200ed77dc7524"
{'users': ['tarek']}

$ curl -X DELETE http://localhost:5000/users -H "X-Messaging-Token:tarek-a15fa2ea620aac8aad3e1b97a64200ed77dc7524"
{'Goodbye': 'tarek}</pre>
</div>
</div>
<div id="messages-managment">
<h3>Messages managment</h3>
<p>Now that we have users, let’s post and get messages. This is done via two very simple functions we’re adding in the <tt>views.py</tt> file:</p>
<div>
<div>
<pre>messages = Service(name='messages', path='/', description="Messages")

_MESSAGES = []

@messages.get()
def get_messages(request):
    """Returns the 5 latest messages"""
    return _MESSAGES[:5]

@messages.post(validator=(valid_token, valid_message))
def post_message(request):
    """Adds a message"""
    _MESSAGES.insert(0, request.validated['message'])
    return {'status': 'added'}</pre>
</div>
</div>
<p>The first one simply returns the five first messages in a list, and the second one inserts a new message in the beginning of the list.</p>
<p>The <strong>POST</strong> uses two validators:</p>
<ul>
<li><tt>valid_token()</tt>: the function we used previously that makes sure the user is registered</li>
<li><tt>valid_message()</tt>: a function that looks at the message provided in the POST body, and puts it in the validated dict.</li>
</ul>
<p>Here’s the <tt>valid_message()</tt> function:</p>
<div>
<div>
<pre>def valid_message(request):
    try:
        message = json.loads(request.body)
    except ValueError:
        request.errors.add('body', 'message', 'Not valid JSON')
        return

    # make sure we have the fields we want
    if 'text' not in message:
        request.errors.add('body', 'text', 'Missing text')
        return

    if 'color' in message and message['color'] not in ('red', 'black'):
        request.errors.add('body', 'color', 'only red and black supported')
    elif 'color' not in message:
        message['color'] = 'black'

    message['user'] = request.validated['user']
    request.validated['message'] = message</pre>
</div>
</div>
<p>This function extracts the json body, then checks that it contains a text key at least. It adds a color or use the one that was provided, and reuse the user name provided by the previous validator with the token control.</p>
</div>
</div>
<div id="generating-the-documentation">
<h2>Generating the documentation</h2>
<p>Now that we have a nifty web application, let’s add some doc.</p>
<p>Go back to the root of your project and install Sphinx:</p>
<div>
<pre>$ bin/pip install Sphinx</pre>
</div>
<p>Then create a Sphinx structure with <strong>sphinx-quickstart</strong>:</p>
<div>
<pre>$ mkdir docs
$ sphinx-quickstart
Welcome to the Sphinx 1.0.7 quickstart utility.

..

Enter the root path for documentation.
&gt; Root path for the documentation [.]: docs
...
&gt; Separate source and build directories (y/N) [n]: y
...
&gt; Project name: Messaging
&gt; Author name(s): Tarek
...
&gt; Project version: 1.0
...
&gt; Create Makefile? (Y/n) [y]:
&gt; Create Windows command file? (Y/n) [y]:</pre>
</div>
<p>Once the initial structure is created, we need to declare the Cornice extension, by editing the <tt>source/conf.py</tt> file. We want to change <strong>extensions = []</strong> into:</p>
<div>
<div>
<pre>import cornice
extensions = ['cornice.sphinxext']</pre>
</div>
</div>
<p>The last step is to document your services by editing the <tt>source/index.rst</tt> file like this:</p>
<div>
<pre>Welcome to Messaging's documentation!
=====================================

.. services::
   :package: messaging</pre>
</div>
<p>The <strong>services</strong> directive is told to look at the services in the <strong>messaging</strong> package. When the documentation is built, you will get a nice output of all the services we’ve described earlier.</p>
</div>
<div id="the-client">
<h2>The Client</h2>
<p>A simple client to use against our service can do three things:</p>
<ol>
<li>let the user register a name</li>
<li>poll for the latest messages</li>
<li>let the user send a message !</li>
</ol>
<p>Without going into great details, there’s a Python CLI against messaging that uses Curses.</p>
<p>See <a href="https://github.com/mozilla-services/cornice/blob/master/examples/messaging/messaging/client.py">https://github.com/mozilla-services/cornice/blob/master/examples/messaging/messaging/client.py</a></p>
<h1>Going deeper</h1>
<p>If you want to dig deeper, here are a few links:</p>
<ul>
<li>Documentation &#8211; <a href="http://packages.python.org/cornice">http://packages.python.org/cornice</a></li>
<li>PyPI &#8211; <a href="http://pypi.python.org/pypi/cornice">http://pypi.python.org/pypi/cornice</a></li>
<li>Repository &#8211; <a href="https://github.com/mozilla-services/cornice">https://github.com/mozilla-services/cornice</a></li>
</ul>
<p>We&#8217;d love feedback &amp; new contributors !</p>
</div>
<br />Filed under: <a href='http://tarekziade.wordpress.com/category/mozilla/'>mozilla</a>, <a href='http://tarekziade.wordpress.com/category/python/'>python</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/tarekziade.wordpress.com/2258/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/tarekziade.wordpress.com/2258/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/tarekziade.wordpress.com/2258/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/tarekziade.wordpress.com/2258/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/tarekziade.wordpress.com/2258/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/tarekziade.wordpress.com/2258/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/tarekziade.wordpress.com/2258/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/tarekziade.wordpress.com/2258/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/tarekziade.wordpress.com/2258/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/tarekziade.wordpress.com/2258/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/tarekziade.wordpress.com/2258/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/tarekziade.wordpress.com/2258/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/tarekziade.wordpress.com/2258/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/tarekziade.wordpress.com/2258/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tarekziade.wordpress.com&amp;blog=448161&amp;post=2258&amp;subd=tarekziade&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://tarekziade.wordpress.com/2011/12/21/tutorial-build-your-web-services-with-cornice/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5e5142d6a1a578f02e2d94c4d6d31088?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">tarek</media:title>
		</media:content>
	</item>
		<item>
		<title>New Year&#8217;s Python Meme</title>
		<link>http://tarekziade.wordpress.com/2011/12/20/new-years-python-meme-2/</link>
		<comments>http://tarekziade.wordpress.com/2011/12/20/new-years-python-meme-2/#comments</comments>
		<pubDate>Tue, 20 Dec 2011 10:28:31 +0000</pubDate>
		<dc:creator>Tarek Ziadé</dc:creator>
				<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://tarekziade.wordpress.com/?p=2238</guid>
		<description><![CDATA[Hey I did this in 2009, let&#8217;s try again &#8212; I am adding one extra question this year 1. What’s the coolest Python application, framework or library you have discovered in 2011 ? GEvent &#38; Pyramid. Not discoveries, but a daily usage. GEvent was for me a fantastic way to make the Firefox Sync Python [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tarekziade.wordpress.com&amp;blog=448161&amp;post=2238&amp;subd=tarekziade&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Hey <a href="http://tarekziade.wordpress.com/2009/12/28/new-years-python-meme">I did this in 2009</a>, let&#8217;s try again &#8212; I am adding one extra question this year</p>
<p><strong>1. What’s the coolest Python application, framework or library you have discovered in 2011 ?</strong></p>
<p><strong>GEvent &amp; Pyramid</strong>. Not discoveries, but a daily usage. GEvent was for me a fantastic way to make the Firefox Sync Python server scale without being forced to write callback-style code. Pyramid is a very elegant framework, that takes the simplicity from Pylons and the power and experience from Repoze &amp; the Zope world. A good sign for me is that we don&#8217;t have to deal with the ZCA <img src='http://s1.wp.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><strong>2. What new programming technique did you learn in 2011 ?</strong></p>
<p><strong>Better behaviour in high loaded server apps</strong>. During the last year, when we wrote all the pieces that makes Firefox Sync today, I&#8217;ve learned how to be more careful on how my apps would react when a back-end breaks or cease to reply, when a database gets slow, or when some service that&#8217;s used restarts &#8212; or when my own app restarts, still hammered by many requests. I did a fair amount of work on this, like smart pools of connectors and better testing techniques, and make decisions on what features survive when some third-party server is down, and what features just go 503.</p>
<p><strong>3. What’s the name of the open source project you contributed the most in 2011 ? What did you do ?<br />
</strong></p>
<p><strong>Mozilla</strong>. I have not contributed as much as last year in Python because my work at Mozilla takes most of my time, but the good news is that all our stuff is open source so.. The most useful stuff for the community we&#8217;ve started is probably <a href="https://github.com/mozilla-services/cornice">Cornice</a>. But we&#8217;ve written and writing a myriad of apps and libs. See <a href="https://github.com/mozilla-services">https://github.com/mozilla-services</a> and <a href="http://hg.mozilla.org/services">http://hg.mozilla.org/services</a></p>
<p>In Python I still interact a bit with what&#8217;s going on in Packaging and hope I&#8217;ll be able to spend more time on it in 2012. But some packaging work I needed at work was also useful for the community, like pypi2rpm.</p>
<p><strong>4. What was the Python blog or website you read the most in 2011 ?</strong></p>
<p>Like in the past few years, Python Reddit. And I think I am not alone in that case. 90% of my blog hits come from Reddit <img src="https://s-ssl.wordpress.com/wp-includes/images/smilies/icon_smile.gif?m=1305848327g" alt=":-)" /></p>
<p><strong>5. What are the three top things you want to learn in 2012 ?</strong></p>
<p>I&#8217;d like to learn how to program in a few new languages, just to give them a shot. Maybe Haskell. I&#8217;d also like to finish a spare project I have started with Benoit, and try to launch it, promote &amp; market it. Last, I&#8217;d like to learn more about Firefox arcanes &#8212; just for my culture.</p>
<p><strong>6. What are the top software, app or lib you wish someone would write in 2012 ?</strong></p>
<ul>
<li>I want to take a picture of a wine bottle and have it recognized in an online app, where I can share my thoughts about its taste.</li>
<li>I want an Android virtual ping-pong application, where you can use your phone as paddle and see the e-ball through the camera &amp; play with a friend.</li>
</ul>
<p>Want to do your own list ? here&#8217;s how:</p>
<ul>
<li>copy-paste the questions and answer to them in your blog</li>
<li>tweet it with the <a href="https://twitter.com/#!/search/%232012pythonmeme">#2012pythonmeme</a> hashtag</li>
</ul>
<br />Filed under: <a href='http://tarekziade.wordpress.com/category/python/'>python</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/tarekziade.wordpress.com/2238/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/tarekziade.wordpress.com/2238/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/tarekziade.wordpress.com/2238/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/tarekziade.wordpress.com/2238/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/tarekziade.wordpress.com/2238/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/tarekziade.wordpress.com/2238/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/tarekziade.wordpress.com/2238/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/tarekziade.wordpress.com/2238/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/tarekziade.wordpress.com/2238/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/tarekziade.wordpress.com/2238/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/tarekziade.wordpress.com/2238/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/tarekziade.wordpress.com/2238/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/tarekziade.wordpress.com/2238/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/tarekziade.wordpress.com/2238/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tarekziade.wordpress.com&amp;blog=448161&amp;post=2238&amp;subd=tarekziade&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://tarekziade.wordpress.com/2011/12/20/new-years-python-meme-2/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5e5142d6a1a578f02e2d94c4d6d31088?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">tarek</media:title>
		</media:content>

		<media:content url="https://s-ssl.wordpress.com/wp-includes/images/smilies/icon_smile.gif?m=1305848327g" medium="image">
			<media:title type="html">:-)</media:title>
		</media:content>
	</item>
		<item>
		<title>Mozilla Apps &#8212; server side</title>
		<link>http://tarekziade.wordpress.com/2011/12/14/mozilla-apps-server-side/</link>
		<comments>http://tarekziade.wordpress.com/2011/12/14/mozilla-apps-server-side/#comments</comments>
		<pubDate>Wed, 14 Dec 2011 13:43:38 +0000</pubDate>
		<dc:creator>Tarek Ziadé</dc:creator>
				<category><![CDATA[mozilla]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://tarekziade.wordpress.com/?p=2208</guid>
		<description><![CDATA[Yesterday, we&#8217;ve launched the Developer Preview for Apps, you can play with at https://apps-preview.mozilla.org The server side is composed of many pieces, and while they are subject to change since this is just a preview, I think it&#8217;s quite interesting to describe some of them already &#8212; and maybe get more contributors in the process, [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tarekziade.wordpress.com&amp;blog=448161&amp;post=2208&amp;subd=tarekziade&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Yesterday, we&#8217;ve launched the <em><strong>Developer Preview</strong></em> for Apps, you can play with at <a href="https://apps-preview.mozilla.org/">https://apps-preview.mozilla.org</a></p>
<p>The server side is composed of many pieces, and while they are subject to change since this is just a preview, I think it&#8217;s quite interesting to describe some of them already &#8212; and maybe get more contributors in the process, since everything is open source and contributors are welcome.</p>
<p>Here&#8217;s an overview of the system &#8212; we used:</p>
<ul>
<li><strong>Django</strong> for the App MarketPlace</li>
<li><strong>Cornice</strong> for the Sync APIs</li>
<li><strong>Node.js</strong> for the Sauropod APIs</li>
<li><strong>HBase</strong> for the Sauropod DB</li>
</ul>
<h3>The App MarketPlace &#8211; Django</h3>
<p>The App MarketPlace located at <a href="https://apps-preview.mozilla.org">https://apps-preview.mozilla.org</a> is where you can upload your own Apps, or install some. There&#8217;s a payment process for non-free Apps, and you can see which one you have bought in your profile.</p>
<p>The development is driven by the WebDev team, and is based on Django &#8212; see <a href="https://github.com/mozilla/zamboni/tree/master/apps/webapps">https://github.com/mozilla/zamboni/tree/master/apps/webapps</a></p>
<p>I can&#8217;t really describe this part, as I did not follow it closely. But basically, the Market Place keeps track of your apps and payment receipts, for other parts of the system to interact with.</p>
<h3>The Dashboard &#8211; HTML + JS</h3>
<p>Once you start to install Open Web Applications, you are redirected to a <em>Dashboard</em> at <a href="https://myapps.mozillalabs.com">https://myapps.mozillalabs.com</a>. This Dashboard is an HTML application that lists your installed Apps associated to your Browser ID.</p>
<p>What&#8217;s pretty cool is that no matter where you&#8217;ve installed a given App &#8212; Firefox on your Desktop, your Phone, it will appear on this dashboard, and synced across devices.This is done via a Sync service called <em><strong>AppSync</strong></em>.</p>
<p>Code pointers for the Dashboard:</p>
<ul>
<li><a href="https://github.com/mozilla/openwebapps/tree/develop/site">https://github.com/mozilla/openwebapps/tree/develop/site</a></li>
<li><a href="https://github.com/mozilla/openwebapps/blob/develop/addons/jetpack/lib/sync.js">https://github.com/mozilla/openwebapps/blob/develop/addons/jetpack/lib/sync.js</a></li>
</ul>
<h3>AppSync</h3>
<p>AppSync is the part I worked on. Its design was mainly done by Ian Bicking, who then worked on the client side implementation while I was working on the server side one.</p>
<p>It&#8217;s quite similar to what we did for Firefox Sync, except that:</p>
<ul>
<li>AppSync supports BrowserID</li>
<li>The data is stored in Sauropod</li>
</ul>
<p>Securing this data is part of a much larger ongoing project called <a href="https://wiki.mozilla.org/Sauropod">Sauropod</a>. The idea is that any database access has to be done with credentials, and that Sauropod is in charge of controlling them and dealing with the storage.</p>
<p>In the long term, depending how Sauropod evolves with respect to encryption, and how Firefox Sync itself evolves with respect to Browser ID and Sauropod access, we might merge both projects.</p>
<p>Or maybe Sauropod will provide APIs one day that are good enough for direct clients interactions, turning AppSync into a simple proxy ?</p>
<p>Time will tell !</p>
<p>Anyway, here&#8217;s an overview below of the AppSync system we&#8217;ve set up for this preview.</p>
<p>We have the AppSync server itself, that&#8217;s built using <a href="http://packages.python.org/cornice/">Cornice</a>. It provides the synchronisation APIs described in this document: <a href="https://wiki.mozilla.org/Apps/Sync/Spec">https://wiki.mozilla.org/Apps/Sync/Spec</a></p>
<p>Every time a client wants to write new data, we call the <em><strong>Sauropod</strong></em> server which is a very simple GET/SET api built with Node.js.</p>
<p>The flow is:</p>
<ul>
<li>AppSync server asks for a new Sauropod session, using Browser ID credentials</li>
<li>Sauropod verifies the Browser ID credentials then create a DB token into a session</li>
<li>AppSync uses this token until its not valid anymore</li>
<li>Sauropod calls in turn an HBase cluster to access the data</li>
<li>Every write is mirrored in a MySQL database in AppSync. This mirroring was set so we can turn off Sauropod if we need to, and still have a working system. This will eventually go away later.</li>
</ul>
<p><img class="alignnone" title="AppSync Cluster" src="http://ziade.org/appsync.png" alt="" width="464" height="556" /></p>
<p>Find the code here:</p>
<ul>
<li>Server <a href="https://github.com/mozilla/appsync">https://github.com/mozilla/appsync</a></li>
<li>Client <a href="https://github.com/mozilla/openwebapps/tree/develop/sync">https://github.com/mozilla/openwebapps/tree/develop/sync</a></li>
</ul>
<h3>What&#8217;s Next</h3>
<p>I am really excited by this project. There are a lot of people involved in the Mozilla community, and seeing all the moving pieces assembled to build an <em><strong>Open</strong></em> App environement is pretty cool.</p>
<p>We&#8217;re going to work in the upcoming months on consolidating the whole system, making sure it scales well and correct the design as the feedback comes back.</p>
<p>If you want to get involved, you can install the preview, play with the available Apps and even maybe write your own Apps for the Market Place, or help us in the coding.</p>
<p>We&#8217;re hanging in #openwebapps on Mozilla&#8217;s IRC</p>
<p><strong>EDIT : <a href="http://kix.in/2011/12/15/behind-the-mozilla-apps-developer-preview/">Anant wrote a very nice blog post on the topic</a></strong></p>
<p>&nbsp;</p>
<br />Filed under: <a href='http://tarekziade.wordpress.com/category/mozilla/'>mozilla</a>, <a href='http://tarekziade.wordpress.com/category/python/'>python</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/tarekziade.wordpress.com/2208/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/tarekziade.wordpress.com/2208/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/tarekziade.wordpress.com/2208/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/tarekziade.wordpress.com/2208/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/tarekziade.wordpress.com/2208/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/tarekziade.wordpress.com/2208/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/tarekziade.wordpress.com/2208/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/tarekziade.wordpress.com/2208/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/tarekziade.wordpress.com/2208/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/tarekziade.wordpress.com/2208/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/tarekziade.wordpress.com/2208/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/tarekziade.wordpress.com/2208/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/tarekziade.wordpress.com/2208/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/tarekziade.wordpress.com/2208/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tarekziade.wordpress.com&amp;blog=448161&amp;post=2208&amp;subd=tarekziade&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://tarekziade.wordpress.com/2011/12/14/mozilla-apps-server-side/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5e5142d6a1a578f02e2d94c4d6d31088?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">tarek</media:title>
		</media:content>

		<media:content url="http://ziade.org/appsync.png" medium="image">
			<media:title type="html">AppSync Cluster</media:title>
		</media:content>
	</item>
		<item>
		<title>QA script on web services</title>
		<link>http://tarekziade.wordpress.com/2011/12/12/qa-script-on-web-services/</link>
		<comments>http://tarekziade.wordpress.com/2011/12/12/qa-script-on-web-services/#comments</comments>
		<pubDate>Mon, 12 Dec 2011 10:00:38 +0000</pubDate>
		<dc:creator>Tarek Ziadé</dc:creator>
				<category><![CDATA[mozilla]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://tarekziade.wordpress.com/?p=2192</guid>
		<description><![CDATA[The other task Alexis and I are going to work on this week, besides Cornice, is a QA script for web services. The goal is simple : check that a set of web services are HTTP compliant. For example, does your application send the proper 406 error when an unsupported Accept is asked by the [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tarekziade.wordpress.com&amp;blog=448161&amp;post=2192&amp;subd=tarekziade&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>The other task Alexis and I are going to work on this week, besides Cornice, is a QA script for web services.</p>
<p>The goal is simple : check that a set of web services are HTTP compliant. For example, does your application send the proper 406 error when an unsupported Accept is asked by the client ?</p>
<p>If you document properly your web services, asking for an unsupported Accept should not occur of course, but in most projects those protocol details are often a bit vague. And someone that writes a client software will inevitably make some assumptions based on his HTTP knowledge on how the application is supposed to behave.</p>
<p>Richard Newman came up with a fair list of tests we could run against a web app already, and we&#8217;ve started to summarise and add more of them here: <a href="https://wiki.mozilla.org/Services/WALint">https://wiki.mozilla.org/Services/WALint</a></p>
<p>The idea of the script is to print out a report of errors and warnings it found on a web app, exactly like a lint tool would do on some code. That&#8217;s what I called it <em><strong>WALint</strong></em> (Web App Lint). Alexis doesn&#8217;t like the name but he did not find a better name yet <img src='http://s1.wp.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>The way it works is that you describe in a configuration file the URIs of your web services, then WALint runs tests against them, using what we called <em>controllers</em>.</p>
<p>Each controller is in charge of trying out something on the web app, using a small HTTP test client (using WebTest), given a path and a method.  WALint will provide built-in controllers and will be extensible. We will have Mozilla-specific tests, like the maximum size of a query string, or the maximum size of the request, since those limits are specific to the used stack.</p>
<p>We got bitten by this is the past in Sync &#8211; one web service failed to work properly because the client was building a super long query string, that was truncated along the way in our stack.</p>
<p>Our final goal with this tool is to be able to add in Jenkins these controls for all our web apps, and catch more problems before they occur in production.</p>
<p>Since it&#8217;s also useful while you build your code, WALint will have a UnitTest integration, so you can run it as a functional test from within your test suite &#8212; In that case, it will run directly against the code.</p>
<p>As usual, feedback &amp; contributions are welcome. The code is being built here: <a href="https://github.com/mozilla-services/walint">https://github.com/mozilla-services/walint</a></p>
<br />Filed under: <a href='http://tarekziade.wordpress.com/category/mozilla/'>mozilla</a>, <a href='http://tarekziade.wordpress.com/category/python/'>python</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/tarekziade.wordpress.com/2192/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/tarekziade.wordpress.com/2192/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/tarekziade.wordpress.com/2192/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/tarekziade.wordpress.com/2192/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/tarekziade.wordpress.com/2192/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/tarekziade.wordpress.com/2192/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/tarekziade.wordpress.com/2192/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/tarekziade.wordpress.com/2192/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/tarekziade.wordpress.com/2192/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/tarekziade.wordpress.com/2192/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/tarekziade.wordpress.com/2192/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/tarekziade.wordpress.com/2192/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/tarekziade.wordpress.com/2192/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/tarekziade.wordpress.com/2192/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tarekziade.wordpress.com&amp;blog=448161&amp;post=2192&amp;subd=tarekziade&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://tarekziade.wordpress.com/2011/12/12/qa-script-on-web-services/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5e5142d6a1a578f02e2d94c4d6d31088?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">tarek</media:title>
		</media:content>
	</item>
		<item>
		<title>Cornice &#8211; Validators and 406s brought to you by Alexis</title>
		<link>http://tarekziade.wordpress.com/2011/12/07/cornice-validators-and-406s-brought-to-you-by-alexis/</link>
		<comments>http://tarekziade.wordpress.com/2011/12/07/cornice-validators-and-406s-brought-to-you-by-alexis/#comments</comments>
		<pubDate>Wed, 07 Dec 2011 18:09:56 +0000</pubDate>
		<dc:creator>Tarek Ziadé</dc:creator>
				<category><![CDATA[mozilla]]></category>
		<category><![CDATA[pyramid]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://tarekziade.wordpress.com/?p=2174</guid>
		<description><![CDATA[Alexis started to work with me this week from my house and we&#8217;re having good times. More geeks from Afpy are joining us this week-end for wine-drinking and working on a Python technical writing project. While working myself on AppSync with the fine folks from Mozilla Labs,  I am mentoring Alexis to get him up [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tarekziade.wordpress.com&amp;blog=448161&amp;post=2174&amp;subd=tarekziade&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://notmyidea.org/">Alexis</a> started to work with me this week from my house and we&#8217;re having good times. More geeks from Afpy are joining us this week-end for wine-drinking and working on a Python technical writing project.</p>
<p>While working myself on <a href="https://wiki.mozilla.org/Apps/Sync/Spec">AppSync</a> with the fine folks from Mozilla Labs,  I am mentoring Alexis to get him up to speed on our projects &amp; standards at Mozilla Services.<a href="http://tarekziade.files.wordpress.com/2011/12/alexis1.jpg"><img class="alignright  wp-image-2180" title="alexis" src="http://tarekziade.files.wordpress.com/2011/12/alexis1.jpg?w=455&#038;h=304" alt="" width="455" height="304" /></a></p>
<p><a href="http://packages.python.org/cornice/">Cornice</a>, is a perfect match for him to start working &#8212; it&#8217;s isolated enough so he can have fun and produce features that are immediately useful, yet learn our standards &amp; processes.</p>
<p>So we worked on its design with the help of its principal user, Ben Bangert, and I asked Alexis to blog about the work &amp; doc we produced since Monday.</p>
<p>Read up =&gt; <a href="http://blog.notmyidea.org/introducing-cornice.html"><strong>Introducing Cornice</strong></a></p>
<br />Filed under: <a href='http://tarekziade.wordpress.com/category/mozilla/'>mozilla</a>, <a href='http://tarekziade.wordpress.com/category/pyramid/'>pyramid</a>, <a href='http://tarekziade.wordpress.com/category/python/'>python</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/tarekziade.wordpress.com/2174/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/tarekziade.wordpress.com/2174/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/tarekziade.wordpress.com/2174/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/tarekziade.wordpress.com/2174/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/tarekziade.wordpress.com/2174/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/tarekziade.wordpress.com/2174/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/tarekziade.wordpress.com/2174/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/tarekziade.wordpress.com/2174/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/tarekziade.wordpress.com/2174/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/tarekziade.wordpress.com/2174/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/tarekziade.wordpress.com/2174/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/tarekziade.wordpress.com/2174/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/tarekziade.wordpress.com/2174/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/tarekziade.wordpress.com/2174/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tarekziade.wordpress.com&amp;blog=448161&amp;post=2174&amp;subd=tarekziade&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://tarekziade.wordpress.com/2011/12/07/cornice-validators-and-406s-brought-to-you-by-alexis/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5e5142d6a1a578f02e2d94c4d6d31088?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">tarek</media:title>
		</media:content>

		<media:content url="http://tarekziade.files.wordpress.com/2011/12/alexis1.jpg?w=1024" medium="image">
			<media:title type="html">alexis</media:title>
		</media:content>
	</item>
		<item>
		<title>Syntastic now with Flake8</title>
		<link>http://tarekziade.wordpress.com/2011/12/04/syntastic-now-with-flake8/</link>
		<comments>http://tarekziade.wordpress.com/2011/12/04/syntastic-now-with-flake8/#comments</comments>
		<pubDate>Sun, 04 Dec 2011 21:36:45 +0000</pubDate>
		<dc:creator>Tarek Ziadé</dc:creator>
				<category><![CDATA[mozilla]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://tarekziade.wordpress.com/?p=2170</guid>
		<description><![CDATA[If you&#8217;re a VIM user and a Python coder, that could interest you. Syntastic, a syntax checker for VIM now includes Flake8 as a checker for Python code. Syntastic can be used to check for syntax errors in files opened in VIM. It has a pretty extensive list of supported languages. For Python it had [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tarekziade.wordpress.com&amp;blog=448161&amp;post=2170&amp;subd=tarekziade&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re a VIM user and a Python coder, that could interest you.</p>
<p><a href="http://www.vim.org/scripts/script.php?script_id=2736">Syntastic</a>, a syntax checker for VIM now includes <a href="http://pypi.python.org/pypi/flake8">Flake8</a> as a checker for Python code.</p>
<p>Syntastic can be used to check for syntax errors in files opened in VIM. It has a pretty extensive list of supported languages.</p>
<p>For Python it had PyFlakes, and since the latest version, it has my small glue script &#8220;Flake8&#8243;, that reunites in a single stream: pep8, PyFlakes and a McCabe checker.</p>
<p>For Flake8 the next step is to support Python 3 &#8212; as soon as I find some time, or a volunteer <img src='http://s1.wp.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Thanks to <em>Sylvain Soliman</em> (and Clayton Parker) !</p>
<br />Filed under: <a href='http://tarekziade.wordpress.com/category/mozilla/'>mozilla</a>, <a href='http://tarekziade.wordpress.com/category/python/'>python</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/tarekziade.wordpress.com/2170/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/tarekziade.wordpress.com/2170/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/tarekziade.wordpress.com/2170/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/tarekziade.wordpress.com/2170/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/tarekziade.wordpress.com/2170/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/tarekziade.wordpress.com/2170/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/tarekziade.wordpress.com/2170/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/tarekziade.wordpress.com/2170/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/tarekziade.wordpress.com/2170/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/tarekziade.wordpress.com/2170/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/tarekziade.wordpress.com/2170/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/tarekziade.wordpress.com/2170/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/tarekziade.wordpress.com/2170/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/tarekziade.wordpress.com/2170/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tarekziade.wordpress.com&amp;blog=448161&amp;post=2170&amp;subd=tarekziade&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://tarekziade.wordpress.com/2011/12/04/syntastic-now-with-flake8/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5e5142d6a1a578f02e2d94c4d6d31088?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">tarek</media:title>
		</media:content>
	</item>
		<item>
		<title>Cornice &#8212; web services with Pyramid</title>
		<link>http://tarekziade.wordpress.com/2011/11/29/cornice-web-services-with-pyramid/</link>
		<comments>http://tarekziade.wordpress.com/2011/11/29/cornice-web-services-with-pyramid/#comments</comments>
		<pubDate>Tue, 29 Nov 2011 10:18:53 +0000</pubDate>
		<dc:creator>Tarek Ziadé</dc:creator>
				<category><![CDATA[mozilla]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://tarekziade.wordpress.com/?p=2141</guid>
		<description><![CDATA[Since we&#8217;ve initially started Cornice at Services, we had more discussion about how we could make it easier for developers to validate an incoming request. Our goal is : to be able to validate a request and if needed, to convert it to specific data structures to complete the documentation of our web services in [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tarekziade.wordpress.com&amp;blog=448161&amp;post=2141&amp;subd=tarekziade&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Since we&#8217;ve <a href="https://tarekziade.wordpress.com/2011/10/21/building-web-services-with-pyramid/">initially started Cornice at Services</a>, we had more discussion about how we could make it easier for developers to validate an incoming request.</p>
<p>Our goal is :</p>
<ul>
<li>to be able to validate a request and if needed, to convert it to specific data structures</li>
<li>to complete the documentation of our web services in Sphinx with those validation steps</li>
</ul>
<p>Here&#8217;s a concrete example: A <em>PUT</em> request used to create a user in a database should come as a JSON object in the request body, which content would be validated and turned into a Person object, then sent to a SQL backend.</p>
<p>The web service needs in that case to reject any malformed request with a 400, and we&#8217;d also want to document this constraint in the web service documentation.</p>
<p>There are some existing tools in the validation arena, like <a href="http://www.formencode.org/en/latest/index.html">FormEncode</a> or <a href="http://docs.pylonsproject.org/projects/colander/en/latest/">Colander</a>.</p>
<p>FormEncode <del></del>and Colander both provide data validation via schemas, and FormEncode offers HTMLform generation.</p>
<p>When you need to validate an incoming request in your web service, those tools can fit your needs or simply be overkill. So, we wanted to integrate a validation step in Cornice without forcing the usage of a specific validation tool.</p>
<h3>A simple callable</h3>
<p>What we did is added a <em>validator</em> option that needs to point to a callable. The callable receives the request object and has to return an HTTP error code followed by a reason in case the request does not comply.</p>
<p>Here&#8217;s an example, a <strong><em>GET /foo</em></strong> that will return a 402 if the<strong><em> X-Paid</em></strong> header is missing :</p>
<pre>    from cornice import Service

    foo = Service(name='foo', path='/foo')

    def has_paid(request):
        """The request must have an X-Paid header containing a token.

        This header proves the user has paid
        """
        if not 'X-Paid' in request.headers:
            return 402, 'You need to pay !'

    @foo.get(validator=has_paid)
    def get_value(request):
        """Returns the value.
        """
        return 'Hello'</pre>
<p>From there, Cornice will call <em>has_paid</em> prior to <em>get_value</em>. Cornice is also able to build the documentation of the web service, by merging the docstrings of <em>get_value</em> and <em>has_paid</em>.</p>
<h3>Sphinx integration</h3>
<p>We provide a Sphinx extension for documenting a Cornice based project. You can inject in your Sphinx document the web service description, via a <em><strong>service</strong></em> directive.</p>
<pre>.. services::
   :package: demoapp</pre>
<p>In this example, the directive looks for all Cornice definitions in the <em><strong>demoapp</strong></em> package by scanning it, and injects their documentation in the Sphinx document.</p>
<p>The service directive provides a few options. For instance the <em><strong>name</strong></em> option will let you inject the documentation of one specific web service.</p>
<h3>Colander integration</h3>
<p>I said earlier simple callables where good enough for simple validation cases. Let&#8217;s take a more complex example.</p>
<p>Let&#8217;s say, you have a <em><strong>Person</strong></em> schema in Colander, that defines a person&#8217;s attributes &#8212; <a href="http://docs.pylonsproject.org/projects/colander/en/latest/basics.html#defining-a-schema-imperatively">See Colander docs for details</a>.</p>
<p>And you want to provide a <em><strong>PUT</strong></em> Web Service to create a person, where the request body is the person data serialized in JSON.</p>
<p>Here&#8217;s the full Cornice definition</p>
<pre>   from cornice import Service
   from cornice.schemas import save_converted, get_converted

   def check_person(request):
      """The request body must be a JSON object describing the Person"""
      try:
          person = json.loads(request)
      except ValueError:
          return 400, 'Bad Json data!'

      schema = Person()
      try:
          deserialized = schema.deserialized(person)
      except InvalidError, e:
           # the struct is invalid
           return 400, e.message

      save_converted(request, 'person', deserialized)

    service = Service(name='person', path='/person/{id}')

    @service.put(validator=check_person)
    def data_posted(request):
        person = get_converted(request, 'person')
        ... do the work on person ...</pre>
<p>In this example, the validator checks that the request body is valid Json, then pass the unserialized mapping to Colander to check that it&#8217;s a valid Person record. Last, it uses the <em><strong>save_converted</strong></em> function we provide, to save the Person object into the request.</p>
<p>The web service then can pick it up with the <em><strong>get_converted</strong></em> function.</p>
<h3>Next Steps</h3>
<p>Our next steps is to build a library of useful built-in validators. Things like:</p>
<ul>
<li>is the request body is JSON ?</li>
<li>do we have param X, if yes is it an integer ?</li>
<li>any reusable validator we&#8217;ll think about</li>
</ul>
<p>The final goals here are :</p>
<ol>
<li>have our web services code written in two phases: the validation phase, and the code itself. Because they are a lot of reusable bits in that first phase.</li>
<li>reuse as much as possible docstrings to document our web services, to avoid the <em>doc-is-not-up-to-date-anymore</em> plague</li>
</ol>
<p>You can follow the development of Cornice here: <a href="https://github.com/mozilla-services/cornice">https://github.com/mozilla-services/cornice</a></p>
<p>And even participate by joining our Mailing List: <a href="https://mail.mozilla.org/listinfo/services-dev">https://mail.mozilla.org/listinfo/services-dev</a></p>
<br />Filed under: <a href='http://tarekziade.wordpress.com/category/mozilla/'>mozilla</a>, <a href='http://tarekziade.wordpress.com/category/python/'>python</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/tarekziade.wordpress.com/2141/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/tarekziade.wordpress.com/2141/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/tarekziade.wordpress.com/2141/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/tarekziade.wordpress.com/2141/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/tarekziade.wordpress.com/2141/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/tarekziade.wordpress.com/2141/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/tarekziade.wordpress.com/2141/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/tarekziade.wordpress.com/2141/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/tarekziade.wordpress.com/2141/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/tarekziade.wordpress.com/2141/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/tarekziade.wordpress.com/2141/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/tarekziade.wordpress.com/2141/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/tarekziade.wordpress.com/2141/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/tarekziade.wordpress.com/2141/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tarekziade.wordpress.com&amp;blog=448161&amp;post=2141&amp;subd=tarekziade&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://tarekziade.wordpress.com/2011/11/29/cornice-web-services-with-pyramid/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5e5142d6a1a578f02e2d94c4d6d31088?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">tarek</media:title>
		</media:content>
	</item>
	</channel>
</rss>
