Thursday, May 10, 2007

Creating Rich Internet Applications with Python

I have been looking for the ideal tool for creating Rich Internet Applications (RIA) with Python. Although there is a ton of web frameworks out there, my favorite being Turbogears, all of them have so far failed to jump in the RIA bandwagon. I have been playing with OpenLaszlo, which although quite visually stunning, is a bit hard to integrate with a Python backend (but I am working on it, stay tuned!).

So yesterday I came across this other framework called Rialto which is marketed as language agnostic. They directly support Python (among other dynamic languages). They also say that their goal is to enable people to create RIAs without having to write DHTML, javascript or understanding DOM concepts.

They have a tutorial integrating their toolkit with CherryPy, so to teach my self Rialto, I decided to port their tutorial to TurboGears . Read along for how to make a simple app looking like the figure below.

I assume readers of this howto will be somewhat familiar with TurboGears, otherwise what's the point? So the first step is to generate a bare-bones TurboGears app with "tg-admin quickstart". Then Download and install rialtoPython from the Rialto website.

Then go to you controllers.py and first add the required import line:
from rialtoPython import *

Then, in the class root, empty the guts of the index method. Change the decorator of this method to:
@expose
def index(self):

Now we can proceed to insert the Rialto content inside the method. RialtoPython works by assembling the HTML page as a big string using python objects to generate the javascript parts. It's easy for a simple example like this but might get out of hand quickly for larger projects. I believe the python calls made within the index method could be done inside a Kid template, separating the view from the controller part as it is expected in a Turbogears application.

Here is the contents of the index Method:

@expose()
def index(self):
rp = rialtoPython.RialtoPython()
out = []
DIV = "document.body"
LAYOUT = "ihmDemo"
WINDOW = "myWindow"
WINDOW_TITLE = "Rialto-Turbogears Integration Example"
FRAME = "boxDemo"
FORM = "myForm"
URL = "do"
# assembling the page
out.append(rp.addImport(devMode=False))
out.append('')
out.append('\trialto/I18N.setLanguage("en");\n')
#layout
out.append(rp.openLayout(LAYOUT))
#app components
out.append(rp.windowTag(WINDOW, WINDOW_TITLE, DIV))
out.append(rp.frameTag(FRAME, '30', '30', '300', '120', 'My 1st python Box', 'true', 'false', 'relative', 'false', WINDOW))
out.append(rp.formTag(FORM,URL,FRAME))
out.append(rp.labelTag('label1', '25', '10', 'Spam', FORM))
out.append(rp.textTag('login', '25', '90', '200', 'A', FORM, 'true', 'true', 'Eggs'))

out.append(rp.buttonTag('doLogon', 'Ni!', '70', '10', 'And now to something completely different', ['FORM', FORM], FORM))
out.append(rp.buttonTag('default', 'Camelot!', '70', '100', 'The television reception isnt good here anyway', ['FORM', FORM], FORM))
# close the layout Tag
out.append(rp.closeLayout(LAYOUT))
out.append(rp.init(LAYOUT))
# Completing the Html code
out.append('\n')
out.append('\n\n')
return " ".join(out)
Let's now go over how it works, in the beginning of the index method, the RialtoPython is instantiated and some variables are defined in order to make the following calls a little more readable.

All "rp" methods called, return strings that are stored sequentially in the "out" list and the joined into a single string which contains the complete code of the application page. The App contains a frame with a form in it containing a text lable, a text input box, and a couple of buttons, when we call the method that returns the form code, a URL is specified to handle the the data coming from the form. On Turbogears, the URLs are exposed methods of the Root class. So let us write this method:

@expose()
def do(self,login,action):
res=rialtoPython.RialtoPython()
out=[]
error_msg=[]
if action=='doLogon':
if login=="":
error_msg.append("Empty Spam")
elif login!="Eggs":
error_msg.append("Unknown Spam")
if len(error_msg)>0:
out.append(res.showAlert('myAlert', ','.join(error_msg)))

else:
out.append(res.showAlert('myAlert', 'This Spam was good!'))
elif action == 'default':
out.append(res.showAlert('myAlert', 'Are you sure, you want to go to camelot?'))

else:
out.append(res.showAlert('myAlert', 'I dont know anything about the action %s'% action))

return ''.join(out)


The method "do" shows a floating alert window in response to pressing a button in the form. The method takes two arguments: "login", which is the contents of the input text box of the same name. Action is generated by the rialto API and contains the name of the button pressed.

There is only a couple of other things left for us to do before our app is ready:
  1. You have to download the Rialto javascript API source distribution, and unzip it in the same directory we have our controllers.py. After you do that, you should have a "rialtoEngine" directory in it.
  2. Now you have to add the following code to your app.cfg in order to let Turbogears find the Rialto code:
[/rialtoEngine]
static_filter.on=True
static_filter.dir="%(top_level_dir)s/rialtoEngine"

[/config.js]
static_filter.on=True
static_filter.file="%(top_level_dir)s/rialtoEngine/config.js"

[/javascript]
static_filter.on=True
static_filter.dir="%(top_level_dir)s/rialtoEngine/javascript"

[/rialto.js]
static_filter.on=True
static_filter.file="%(top_level_dir)s/rialtoEngine/javascript/rialto.js"

[/images]
static_filter.on=True
staticFilter.dir="%(top_level_dir)s/rialtoEngine/images"

[/style]
static_filter.on=True
static_filter.dir="%(top_level_dir)s/rialtoEngine/style"
Now just start your application and point your browser to http://localhost:8080 to see your first rich internet application, written entirely in Python, running.

Tips: This code may require the latest version of RialtoPython released in may 2007.

Saturday, May 5, 2007

Running OLPC on VirtualBox

I have this project that I have been meaning to port to the OLPC but had been postponing to wait for a more mature development environment.
Well, with the release date set for october, I decided that waiting is no longer an option. On my main machine I have the sugar-jhbuild environment, which is OLPC's gui built from scratch within a Linux environment and the Qemu image which boots normally, but that is a bit too slow for my taste.

So decide to try and run OLPC from VirtualBox, a GPL'd new virtualization tool that I have been quite happilly using lately (much better than VmWare).

So this post is intended as a "how to run OLPC from VirtualBox", type of article. So let's get started:

  1. My start point is an Ubuntu Feisty, with VirtualBox already installed. Installing VirtualBox on an Ubuntu box is a matter of pointing and clicking if you have Automatix installed.
  2. First you need to obtain the latest development image from here.
  3. Start VirtualBox by clicking its icon in the menu.
  4. Click on the new button to create a new virtual machine. A wizard dialog will come up. click next, pick a name, "OLPC" for example. In the combo box below pick "Linux 2.6" as OS type. Click next.
  5. Pick the recommended memory size (128MB). Click next.
  6. Since the image you downloaded is a livecd image you don't have to create an HD, so just click next.
  7. Click finish. you are almost done. You are taken back to the main window, and the panel on the left shows the VM you just created.
  8. Click on the icon corresponding to the VM you created. O the right-side panel a descritpion of it will show up.
  9. Click on "CD/DVD-ROM". Check the box that says "mount CD/DVD drive"
  10. Select the "ISO Image File" radio button.
  11. Select the ISO image file you have downloaded previously.
  12. Click ok and you're done! Just go ahead and star your virtual machine!
Now Virtual box will show a console where the typical Linux boot up messages scroll by. After the boot is complete you will be presented with the XO's login screen. Type your name click on the ">" icon and you will be taken to the sugar desktop.Hint: once you click on the desktop mouse and keyboard are captured by the VM. To release them, press the right CTRL key.
Enjoy!

ccp

Amazon