Tuesday, February 27, 2007

Object Publishing with Nevow

Update: Code for the "Nevow Object Series" of blog posts is available here. Note that the examples can be viewed and run as single files or "project style" with code broken out into separate files.

Object publishing is a very simple concept: making code objects accessible over some medium. The medium most often discussed, due to the prevalence of web applications is HTTP/S. For our purposes, the published objects we will discuss are instantiations of python classes written to provide resources over the network.

In the python community, the most famous example of object publishing is the Zope application server. Zope exposes object written in python or with various Zope scripts/products/etc. In an old Zope 2 Book, Zope's object publishing is broken down very simply:
  1. The client sends a request to the server
  2. The server locates the object using the request URL as a map
  3. The server calls the published object with arguments from the request.
  4. The server interprets and returns the results to the client
What we have here is essentially object look-ups by URL. Given the web context, this makes obvious sense.

With such a simple definition of "object publishing", we can begin seeing "object publishing" pretty much anywhere python is used to deliver content or other resources on the web. For instance, Django qualifies as having an object publisher by means of the configuration mechanism whereby one can use regular expressions to map URLs to its "view" objects. We'll come back to Django in a bit.

Twisted's web "framework" Nevow has a object-publishing capabilities that, due to it being controlled by python classes is limited only by the python code you can write. There are four primary mechanisms by which one can publish objects in Nevow:
  • child attributes on a resource
  • child methods on a resource, or
  • dynamic children using the childFactory() method
  • manipulating the traversal of objects via locateChild() method
I will be focusing on the first two, however, before showing examples of these let's cover some minimal background. Twisted services are commonly run using what's called a .tac file ("Twisted Application Configuration"). Here is a trivial example of this:
from twisted.application import service
from twisted.application import strports

from nevow import appserver

import stuff

# instantiate the application
application = service.Application('Site')

# set up the main resource
root = mystuff.SiteRoot()
site = appserver.NevowSite(root)

# setup the web server
server = strports.service('tcp:8080', site)
server.setServiceParent(application)
Give than this file was saved as site.tac (and that there was a sibling file named stuff.py with the resource SiteRoot defined), you would enter twistd -noy site.tac at the system prompt to run this. This would start a server listening on port 8080. But what is SiteRoot? It is a resource we are making available at the root of our application, "publishing" it at http://localhost:8080/. And what would it look like, you ask? Well, a silly example of stuff.py that define SiteRoot might be something like the following:
from nevow import rend
from nevow import loaders

class SiteRoot(rend.Page):

docFactory = loaders.xmlstr('''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"
xmlns:nevow="http://nevow.com/ns/nevow/0.1">
</html>''')
One reason that this is a silly example is that it does nothing other than declare that the published resource will be an XHTML file with a Nevow namespace, providing no methods (and little content). Additionally, it uses the XML "string" loader, instead of using stan or the XML file loader (for using templates from disk). Regardless, if we add a child attribute that points to another class, we can start to see the object publishing behavior of Nevow:
from nevow import rend
from nevow import loaders

class MyStuffResource(rend.Page):

docFactory = loaders.xmlstr('''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"
xmlns:nevow="http://nevow.com/ns/nevow/0.1">
<h1>My Stuff</h1>
</html>''')

class SiteRoot(rend.Page):

docFactory = loaders.xmlstr('''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"
xmlns:nevow="http://nevow.com/ns/nevow/0.1">
</html>''')

child_mystuff = MyStuffResource()
Starting up our application with these changes will allow us to access the root and child object via the following URLs, respectively:
  • http://localhost:8080/
  • http://localhost:8080/mystuff
This demonstrates how to publish objects via the child_ attribute. child_*() methods do the same thing, while offering all the flexibility that comes with methods. For instance, we could define the method child_yourstuff(self, context) in SiteRoot that would check for your username in the application cookie and pass that info when instantiating a UserStuffResource class. Then the URL http://localhost:8080/yourstuff could publish data specific to whatever was available in a data source associated with the username. The child_*() methods do need to return a resource object, though.

This has been a brief run-down on how you can use child_*() methods and child_ attributes to publish objects. In the next installment, I will show how to customize URL traversal for accessing these resources via the locateChild() method. In particular, I will show how to duplicate the Django URL conf functionality in Nevow.

Technorati Tags: , , ,

Saturday, February 24, 2007

Twisted BoF, Part Deux

Yes, we had another BoF today. How could we not? "But why?" you ask. "How could it get any better?" Well, if it wasn't better, it was just as insanely awesome as last night's. Only completely different.



I don't want to give away too much... there are many others who have a much greater right to share (and celebrate!) this news with you. So I will tease and tantalize instead: exciting things are afoot in the Twisted community. If you ever were curious about diving into Twisted and decided not to, now is definitely the time to reconsider, start checking it out, learning, and getting involved. You won't want to miss out on this.



"Do you know what I'm talking about?"

"The Matrix?"

"Do you want to know what - it - is?"




Technorati Tags: , , , ,

Friday, February 23, 2007

The Twisted Conference

I just got up to my hotel room from the BEST freakin' BoF tonight. Not only were there way more people than any of us expected, but most hung in there like CHAMPS: we started at 8:30pm and didn't get out until almost midnight! Okay, that's a little exaggeration... it was more like 11:30pm. Those present represented the spectrum of new users to intermediate through "founding members", and it was a damned trip. Just tons of amazing energy and latent excitement. And the love, baby -- you could just feel the love :-)



This came as a surprise to many of us, considering that 1) like last year, there are no Twisted talks and 2) most of the Twisted folks didn't know who all was showing up and we didn't think there'd more than a few. At last count, there are eight of us here now, and when Itamar shows up tomorrow, that will make nine.



But back to the BoF: the energy was truly palpable and the room was pretty packed. The topics covered were diverse and very interesting. The questions were stimulating, the answers insightful (and often hilarious). It was, in essence a conference within a conference :-) I believe over half stayed for the duration, and not only did it end with a standing-O (well, we were standing to leave...), but there were cheers and suggestions to do it again tomorrow. An hour later, I'm still pumped and totally incapable of considering sleep. If the enthusiasm of the BoF continues through the rest of the conference, we could end up with a couple sprints...

Technorati Tags: , , ,