« Older Home
Loading Newer »

Grok 1.1a1 with ZTK support

Things happen when you change systems - a few days ago i moved to a new notebook with Ubuntu 9.10 and found myself with a system Python 2.6. I was curious about how to make Grok run on it without patching a number of eggs as i did before a year ago.

Enter Zope Toolkit aka ZTK, a set of libraries intended for reuse by projects like Zope2, Zope3 and Grok. ZTK currently supports Python versions 2.4 - 2.6.

Indeed extending Grok with ZTK versions worked almost out of the box for me. Within a week Souheil Chelfouh, Jan-Wijbrand Kolman and me did all necessary changes and released Grok 1.1a1.

The release is not visible on PyPI atm - but available for download.
You can also use it with grokproject like

$ grokproject --grokversion==1.1a1 project_name

This will install the Grok-1.1a1 release and setup a project as usual. Btw, your project will now run on Python 2.6 too.

We ask all people to test their existing projects with the alpha release and are happy to collect feedback for a second alpha or beta even.

Using Pyjamas with bobo

This weekend i finally came around to connect Pyjamas to my bobo backend application through JSON-RPC. The following example shows all the code you need to enable JSON-RPC in the bobo backend.

Create a file ‘jsonrpc_application.py‘, the bobo backend application:

import bobo

I use lovely.jsonrpc for the JSON-RPC server implementation.

from lovely.jsonrpc.dispatcher import JSONRPCDispatcher

The PyjamasAPI class follows the JSONRPCExample that comes with the Pyjamas distibution. You may want to put your own remote API in here.

class PyjamasAPI(object):
    def echo(self, txt):
        return txt
    def reverse(self, txt):
        return txt[::-1]
    def uppercase(self, txt):
        return txt.upper()
    def lowercase(self, txt):
        return txt.lower()

Now create the jsonrpc dispatcher based on the provided API.

dispatcher = JSONRPCDispatcher(PyjamasAPI())

The next part is all that is needed to make the ‘bobo’ application process JSON-RPC calls.

Define a route, e.g. ‘/jsonrpc’ as the the service endpoint, configure it to return ‘application/json’ and let the dispatcher dispatch the request body. A check for the content type is necessary to get at the correct data from the WebOb request object. Pyjamas e.g. posts the JSON data in ‘x-www-form-urlencoded’ form.

@bobo.post('/jsonrpc', content_type='application/json')
def dispatch(bobo_request):
    content_type = bobo_request.headers['Content-Type']
    if content_type.startswith('application/x-www-form-urlencoded'):
        body = bobo_request.POST.items()[0][0]
    else:
        body = bobo_request.body
    return dispatcher.dispatch(body)

Thats all on the backend side.

In Pyjamas modify ‘examples/jsonrpc/JSONRPCExample.py’ and build it:

class EchoServicePython(JSONProxy):
    def __init__(self):
        JSONProxy.__init__(self, "http://localhost:8080/jsonrpc", \
        ["echo", "reverse", "uppercase", "lowercase"])

At last startup bobo. It is necessary to serve the JSONRPCExample from the bobo application (same domain) like static content:

$ bin/bobo -f jsonrpc_application.py \
           -s /demo=/path/to/examples/jsonrpc/output/

Now point your browser to

$ firefox http://localhost:8080/demo/JSONRPCExample.html

and run the example.

I hope you liked the walktrough. Btw, if you use the Google AppEngine template from my recent blogpost you can run the example almost unmodified from GAE too.

The many faces of Budapest

It was a hot - up to 35 degrees - weekend when Budapest revealed us some of its best views. People were incredibly chilled, taking cooling breaks in the shops at Váci Utca.

Fischerbastei, Budapest
Innenstadt, Budapest
St.Stefan Basilika, Budapest
Déak Ter, Budapest
Inside St.Stephens Basilika, Budapest

Pictures taken August 2009

Open Book Project using Sphinx

Jeff Elkner recently posted in edu-sig mailing list that he spent the last month converting python educational materials from lore to Sphinx at Open Book Project. The results are impressive - the switch to Sphinx adds full-text search and a hyperlinked index to the HTML version. He is now thinking about adding interactive elements to the book through crunchy.

(c) http://openbookproject.net/thinkcs/pythonHow to Think Like a Computer Scientist
Learning with Python 2nd Edition
by Jeffrey Elkner, Allen B. Downey, and Chris Meyers

bobo & GAE

A blueprint on how to setup a new GAE project and run a basic bobo application on top of it.

First download and install the Google App Engine SDK, here is a Tutorial to get you started.

Next create an new package bobo_project. Inside bobo_project add an __init__.py file with empty contents.

    # a package

Now create the app.yaml file. It defines the application id and a single
wildcard URL handler:

    application: your-application-id
    version: 1
    runtime: python
    api_version: 1

    handlers:
    - url: /.*
      script: main.py

The main.py file creates, configures and runs the bobo WSGI application:

    import bobo
    import google.appengine.webapp.util

    bobo_app_name='project'

    def main():
        application = bobo.Application(bobo_resources=bobo_app_name)
        google.appengine.webapp.util.run_wsgi_app(application)

    if __name__ == '__main__':
        main()

project.py is the basic bobo web application:

    import bobo

    @bobo.query('/')
    def hello(name='world'):
        return 'Hello %s' % name

Finally add bobo.py (part of the bobo package) and - if you intend to use JSON - the simplejson package to the project folder (GAE runs on Python2.5).

The project layout now looks like:

    bobo_project/
      __init__.py
      app.yaml
      bobo.py
      main.py
      project.py
      simplejson/

Test-drive your project locally with the dev_appserver:

    gae$ python dev_appserver.py bobo_project &
    gae$ firefox http://localhost:8080/

Create a new appspot project ‘your-application-id’ and upload bobo_project into it:

    gae$ python appcfg.py update bobo_project

Access your application online:

    gae$ firefox http://your-application-id.appspot.com/

Bloomsday again

Dublin streets
Dublin
Dublin
Dublin
and Liffey
Dublin

Pictures taken April 2009

Lazy blogging

I haven’t been blogging much lately, mostly due to severe time limitations and workload. Anyway, here is what i am up to atm …

bobo.digicool.com Working on extensions to bobo, a WSGI framework released by Jim Fulton two weeks ago. bobo is really exciting, as it is super small (40KB including comments), fast (1500 req/sec), fully integrated with paste and has everything you need to start an agile project: URLs (routes and subroutes) mapped to callables - everything else can be supplied by the usual WSGI stack. The subroutes feature is special, not available from other routing packages so far: mapping can start by matching a route and then can traverse into a callable and follow another matched route or traversal and so on (example).

kultur.graz.at In the middle of migrating a collection of Zope2.7 based instances to Zope2.10, testing and fixing small changes in both Zope and the Python interpreter.

medienkunstlabor.at Just finished a new Plone 3 based theme for the Medienkunstlabor website. Creating more Plone 3 themes is definitely on my agenda for the rest of the year.

grok.zope.org Grok 1.0 will be released within the next few months. Working on the transition to WSGI for both Grok and grokproject. The current grokproject 1.0a release is already WSGI enabled. Changing the grok buildout on trunk to a paster based layout is just one bugfix away.

Notables

News of today:

Short notice

Hacker News poll: Pythonic startups: what web framework do you use?

Grok-by-Example: Demosite

This post is part of a series of postings about more or less basic Grok apps that are ported from other python web frameworks. Motivation is that you can look at the original source and the grok code side-by-side and deduce from both. Source is available from svn.zope.org/grokapps/gbedemosite/.

screenshot-gbedemosite.jpg

This “demosite application” shows how to install multiple Grok applications and make them available from a single Grok instance (using ZEO and Apache). A test instance is available at gbe.d2m.at.

Review

Now that you have a few working Grok apps (Grok-By-Example), how about serving them all together from a single Grok instance?

Setup multiple applications for your demosite
One possible setup is to create the demosite as a Grok app on its own. You just construct the basic app layout (or let grokproject do it for you or simply checkout the ‘gbedemosite’ application). I strongly recommend to run your development from inside a virtualenv:

    $ svn co svn://svn.zope.org/repos/main/grokapps/gbedemosite
    $ cd gbedemosite
    $ virtualenv --no-site-packages .
    $ source bin/activate

You then apply the necessary changes for a multi-app setup. Lets start with ’setup.py’. Add the package name of the apps you want to run to the ‘install-requires’ section:

    install_requires=[...
                      'gbeguestbook',
                      'gbe99bottles',
                      'gbewiki',
                      'gbepastebin',
                      ...
                     ],

Now checkout the packages from SVN to your ‘gbedemosite’ folder. If the packages where available from PyPI or another package repository you could just skip this and the next step, buildout would fetch and install the packages on the next run:

    svn co svn://svn.zope.org/repos/main/grokapps/gbeguestbook
    svn co svn://svn.zope.org/repos/main/grokapps/gbe99bottles
    svn co svn://svn.zope.org/repos/main/grokapps/gbewiki
    svn co svn://svn.zope.org/repos/main/grokapps/gbepastebin

In ‘buildout.cfg’ add the same packages to ‘develop’:

    [buildout]
    develop = . gbeguestbook gbe99bottles gbewiki gbepastebin

Run bootstrap (if you have not already) and buildout:

    $ bin/python bootstrap.py
    $ bin/buildout

That’s all for now, lets move on to create the ‘gbedemosite’ app itself.

Create the ‘demosite’ application
You basically only need to change the ‘app.py’ template file. Lets assume you created the app by running “grokproject Demosite”, you already have a ‘Demosite’ application class, with an Index view and the associated ‘app_templates/index.pt’ template file.

You now want to setup all available example apps automatically when creating an instance of the demosite application. Adding an event subscription handler for the ‘Demosite’ class does just that:

    @grok.subscribe(Demosite, grok.IObjectAddedEvent)
    def handle(obj, event):
        applications=(('gbeguestbook.app.Application','Guestbook'),
                      ('gbe99bottles.app.Song','Song'),
                      ('gbewiki.app.WikiPage','Wiki'),
                      ('gbepastebin.app.Application','Pastebin'),
                      )
        for application, name in applications:
            app = zope.component.getUtility(grok.interfaces.IApplication,
                                            name=application)
            try:
                obj[name] = app()
            except DuplicationError:
                pass

The ‘applications’ list defines the example apps and their instance names. Whenever you create a new instance of your ‘Demosite’ class the example apps will be created with their fixed names inside it.

Make your demosite ready for public
If you want to serve your apps to the public, your site also should provide a ‘robots.txt’ file for the webcrawlers.

Add another grok.View to your application class and give it the name ‘robots.txt’:

    class Robots(grok.View):
        grok.name('robots.txt')

Then create another template file in ‘app_templates/robots.pt’. The template could be empty or hold instructions following the robots exclusion standard.

Next create a virtual host to serve the demosite from behind Apache:

    <VirtualHost *>
    ServerName    your.server.name
    ...
    RewriteEngine On
    RewriteRule ^/(.*)  http://127.0.0.1:8080/<demosite>/++vh++http:your.server.name:80/++/$1 [P,L]
    </VirtualHost>

(with <demosite> having the name of your public demosite instance). This should make your apps available at root level. Your ‘app_templates/index.pt’ template already holds links to all installed example apps and serves as default page for the Grok instance. If you need to access the ‘admin’ screens again point your browser to:

    http://localhost:8080/applications

Enable ZEO
Finally you want to debug the running demosite. Some of the example apps have no means to delete existing objects - but you can simply delete objects from the debugger too.

Debugging a running zope instance needs a change in the server setup: you create a ZEO server that holds the ZODB (Data.fs) and 2 ZEO clients that access their data from the ZEO server. One client (’zopectl’) will serve the Demosite application, the other client (’instance2′) will be used for debugging.

You need to change ‘buildout.cfg’, add and modify parts:

    [buildout]
    ...
    parts = ... zodb server instance2

    [zodb]
    recipe = zc.recipe.egg:script
    eggs = ZODB3

    [server]
    recipe = zc.zodbrecipes:server
    zeo.conf =
       <zeo>
          address 8100
       </zeo>
       <filestorage 1>
          path ${buildout:parts-directory}/data/ZEOData.fs
       </filestorage>

    [zopectl]
    recipe = zc.zope3recipes:instance
    application = app
    address = 8080
    zope.conf = devmode on
        <zodb>
          <zeoclient>
            server 8100
          </zeoclient>
        </zodb>
        site-definition ${buildout:parts-directory}/app/site.zcml

        <accesslog>
          <logfile>
            path ${buildout:parts-directory}/zopectl/access.log
          </logfile>
        </accesslog>

        <eventlog>
          <logfile>
            formatter zope.exceptions.log.Formatter
            path STDOUT
          </logfile>
        </eventlog>

    [instance2]
    recipe = zc.zope3recipes:instance
    extends = zopectl
    address = 9080

Finally
Run buildout again, run the tests, start the server, start the client:

    $ bin/buildout
    $ bin/test
    $ bin/server start
    $ bin/zopectl fg

Setup apache:

    $ sudo a2ensite your-vhost-id
    $ sudo /etc/init.d/apache2 restart

Access the demosite admin screens, create a ‘demosite’ instance and use it:

    http://your.server.name/applications

Hope that gets you up and running in record time - creating the demosite application was done in an hour. As always writing the docs took a bit longer ;)



Categories