Archive for the ‘Turbogears’ Category

Coding Binge

Tuesday, January 27th, 2009

I haven’t written to the blog in a while.  Quite frankly, I’ve been busy.  In the last 30 days, I have released 3 software new packages, updated 1, deprecated 1, participated in a sprint that lasted a virtual 2 weeks, closed countless tickets, and pushed forward TG2 functionality.

TG2b4 was released last Saturday.  This was mostly a bug-fix release, but b3 is where the new functionality really came into the scene.  TG2b3 is the first build to include Sprox, a new library for schema-generated widget generation.  Sprox is the offspring of DBSprockets.  I decided I liked the declarative part of DBSprockets so much I wanted to spin it off as it’s own entity.  Sprox looses DBSprocket’s table-based dependency, utilizing the mapping provided by SQLAlchemy.  I realized that much of DBSprocket’s code was doing precisely what SQLSoup was designed to do, and decided to focus my efforts on making and extremely configurable widget base.  The result was a considerable removal of the cruft that was associated with DBSprockets.  Sprox releases with an excellent documentation base provided by Sphinx.

There has been a bit of resistance to Sprox, people were/are confused/upset about my providing yet more options for schema based widget generation.  The fact is I have yet to find anything that performs as well as Sprox from a developer/speed standpoint, and I needed to provide our TurboGears user base with a better way to administrate their site, and also allow them to use that tool component-wise in their system.  I think this method for developing widgets is well done in other frameworks, and we need a solid answer to this problem.  Sprox is just that.

The next step was to re-work Catwalk to use Sprox.  This took a little effort, and I put in RESTful URLs while I was at it, but struggled with making the URLs work within TG2’s dispatch system.  The result was as close to REST as you can get without conforming to a set standard.

The result of hacking REST into Catwalk got me thinking, and I decided to implement content-type dispatch as well as RESTful dipatch in TG2.  I went back for another round on Catwalk, and converted it over to the standard.

I’ve also been toying around with Dojo at NREL.  I’m pretty much done with ExtJS due to licensing issues, a not-so-hot codebase, and weak support from IRC.  It’s bad when you go on to ask a question on the channel as a 6 month-user of a software project and end up spending all your time answering everyone else’s questions (as the most experienced person in the room).  Something must be said for an organization that does not push paid consulting as a primary focus on their website…  #dojo has been an exceptional resource for getting my work done.  Those guys know their software, and lend a great hand to help you with it.

Back to the topic at hand… I was able to shoe-horn Dojo into Sprox with little effort, and implemented DojoCatwalk, which worked, but was ultimately not what I wanted.  What I really wanted was configurability.  I started work on tgext.admin, which was supposed to provide enough functionality to replace tgcrud, a command to auto-create crud in your own TG application.  To support tgext.admin, I created a new package called tgext.crud, which provided a CrudRestController, which is a simple way of providing crud for any object in your model.  AdminController combines this functionality with that of Mark’s lookup code to provide a fast, configurable set of tables/forms/etc for all objects in your model.  AdminController takes a declarative AdminConfig as input which provides a consistent way to create your administrative toolset.  Did I mention it does Dojo tables with ajax loading?  Yeah.

I’m not done with this binge yet.  Catwalk is going to mutate one more time before I’m through with it.  It is going to become a default-configured AdminController specifically designed to work within the context of a quickstarted TG2 application.  I had one blocker ticket which was solved last weekend, so it’s time to get Catwalk good and finished.

DBSprockets is back, Baby!

Friday, December 12th, 2008

So I have had a pretty long hiatus from working on dbsprockets, but I’m back… with a vengeance.  So, I worked hard to get Rum working in TG2, but struggled my ass off and got nowhere.  Left tangled in a web of peak-rules that I did not want to decipher, I began to think about dbsprockets again.  I mean, were we really that far off from what RUM is offering?

The answer turned out to be no.  All I needed to do was to replace the dbsprockets primitives with a class structure.  This turned out to be about an 8 hour job.  Not bad for a day’s work.  And now you can do things like:

from dbsprockets.declaratives import FormBase
from myWebapp.model import User
...
class RegistrationForm(FormBase):
    __model__ = User
    __limit_fields__ = 'user_name', 'email_address', 'display_name', 'password', 'verify'
    __required_fields__ = 'user_name', 'email_address', 'display_name', 'password', 'verify'
    email_address = TextField
    verify = PasswordField('verify')
    __base_validator__ =  Schema(chained_validators=(FieldsMatch('password',
                                                        'verify',
                                                        messages={'invalidNoMatch':
                                                                  "Passwords do not match"}),))
registration_form = RegistrationForm()
class ATurboGearsController(BaseController):
    @validate(form=registration_form.__widget__)
    @expose('genshi:sproxtest.templates.register')
    def register(self, **kw):
        pylons.c.widget = registration_form
        return dict(value={})

This turns out to be a much simpler way of handling forms, because now you can subclass to your heart’s content (for instance, make one base user form which you subclass for admin, registration, profile and login), or even come up with your own wacky WidgetSelector that chooses widgets for you and subclass as you desire. Here is initial documentation, which I will express in more detail at a later date when I have more time to do it the right way.

The simple fact is that you can customize form widgets with ease, limit fields to a set of fields, drop a few fields, basically anything you can think of to change how the database schema actually displays on the page.  The same is true of field validators.  Simply define an attribute of the class that has a validator, widget instance, or widget type, and dbsprockets will do the right thing.  If you want to override both the field and the validator, all you must do is create a widget wit the validator attribute populated.  The greatest thing is that your forms (and tables!) will change with you as your database schema migrates.

Right now I am keeping the primitives way of getting the values from the provider to populate the tables/forms.   This is likely to change in the future.  The primitive way of doing forms is now deprecated.  I will be adding deprecation warnings to the code.  Hooray!

Look for ajax support in the near future on both the view and data side of things.  I have a clear understanding of ExtJS (2.0.1), JSON, and LGPL now and I am not affraid to use it.  In the mean time, a dev version of dbsprockets 0.5 is up at pypi.

Google Summer of Code Mentor Summit Recap

Wednesday, October 29th, 2008

I spent last weekend in Sunnyvale, CA at the GSoC mentor summit.  This was a great opportunity to rub elbows with a number of experts in various OSS projects.  It was great to make connections with people in and out of the Python community.  First off, I just want to thank Google, and Leslie Hawthorne for having us. Google was an excellent host, and I would jump at the chance to attend a Google-hosted event again.  Google is using GSoC to promote the open source community.  By providing funding for students to work for a summer on software instead of flipping burgers, they hope to save the world, one open source project at a time.  I have my own take on what Google’s true intentions are, but I don’t really want to discuss that in this blog entry.  That is to say, I don’t think Google’s intentions are in any way evil, but they are definitely self-serving.  In any event, it is remarkable the amount of time, energy, and money that goes into this project, which is at this time one of a kind.  Here’s hoping that other companies will consider the not-so-small buy in for sponsorship which could lead to even more OSS development.   

As for the summit itself, there were lots of talks.  Since it was run like an open-space conference, it took a little while to work up some speed the first day, but I never found myself want of something to do.  I was not surprised that the talk on monetizing your OSS project was wildly successful.  I was surprised at how easy it was for sessions to get off on tangents, but it was interesting to see how people in similar fields were solving projects.  I attended a session on Scientific Computing (since I work for NREL) and it seemed that the biggest problem the room faced was packaging/deployment of software.  I appears this problem cross-cuts platforms, language, and even hardware barriers.  It also seems that you either have a choice to make: stick with old software that is stable, or upgrade to new stuff that almost always breaks other things.  Sound familiar?  I wonder how long it will be before everyone runs isolated virtual machine images for each of their projects… I bet some already are.  

By day two I was pretty exhausted of participating in sessions, and I just wanted to hack with some like-minded folks.  It turned out that at least 8 people at the summit were hacking on making their application run on Python 2.6, so we all got together and shared the good vibe while we solved our individual problems.  The main barrier for TurboGears 2 running on Python 2.6 was ToscaWidgets and TurboJson.  First off, peak-rules needed some minor tweaking to get a few of the bugs fixed.  Thanks to Philip Eby for implementing my patch (in a slightly different way) and making it all work.  ToscaWidgets was also breaking with the SimpleJson trunk, but this turned out to be an implementation error, and I think I have it mostly sorted out.  

Yesterday evening Mark and I finished up packaging the !first beta! of Turbogears2.  I put a few custom eggs in the index from my GSoC hacking, and suddenly we have a Python 2.6 compatible release.  Also, of interesting note Gustavo Narea cranked out tgext.authorization which handles most of the security for TurboGears2.  Now I just need to get cranking and fix DBSprockets Primitives to work with Rum, and then fix silverplate to support Rum also.  (Perhaps this is my way of telling people to move in the Rum direction).  

Mark and I will be attending PyWorks in November, and doing a sprint then.  So, if you are in town, or interested in sprinting remotely, please don’t hesitate to sign up.  I will be speaking at PyWorks on using PasteScript, Virtualenv, SQLAlchemy, and Nosetests to create robust database applications. Do you think there is anything else I could cram in a 45 minute talk?  I will also be helping Mark out at his TG2 tutorial, so if you aren’t signed up for PyWorks, get crackin’ !

Plonecon Recap

Monday, October 13th, 2008

Last week I attended Plonecon in Washington D.C.  We use Plone quite a bit at NREL, and I  wanted toploneconf come up to speed on the state of the art, and see if I could find some folks to collaborate with on the Scientific Data Management front.   I was not only surprised by the number of people in attendance, but also by the progress being made in forefront of Plone development.

Of course, one of the big news items was what is known in the community as the “Plone tax”, which is a reference to the 30+ seconds it takes to start Plone.  It was announced that this has been reduced to 6 seconds, which in my mind is still too much, but I am glad they are making progress in this area.  [edit] I believe the speedups were achieved in the trunk of plone, not for 3.2.   Plone 3.2 is supposed to be all eggs, which I think is a great benefit to the community.  I have already been using Plone in this manner with Repoze, which packaged Plone as an egg a few months ago.

I was impressed by the changes to the user interface which were proposed by Alexander Limi in his talk on the future of Plone’s user experience.  It looks like portlet/viewlet terminology is being supplanted with the term “widget” which I think is more standard in the web design world. I think the new user interface is more intuitive, simplifying the page down to those components which will be most important, while still making available all of the functionality of Plone.

I was also impressed with Kapil Thangavelu’s content mirror.  While I don’t think his project which takes Plone content and injects it into an sql database will be immediately useful to me, I think it offers a nice path for someone who wants to convert their Zope/Plone site over to an relational-database based site.  It also provides a nice bridge for someone who wants to use existing relational database tools to mine data penned up within a zope database.

Coming from a TG background,  I was of course interested in Repoze.  Chris McDonough gave a compelling talk on repoze, specifically repoze.bfg and what is motivation was for creating yet another framework. We ran a BOF together, and had quite a bit of response.  I demo’d using Toscawidgets within Plone (running on repoze.plone).

Craig Swank and I also demo’d one of our repoze.plone application for a group of people interested in laboratory informatics systems.  I started up a google group for this, and I sincerely hope that our small community can find a way to collaborate efforts in order to increase our productivity in a way only OSS can.

Open Source Software and Production Engineering

Saturday, September 27th, 2008

In the past I have struggled with the fact that some of the OSS code that I write wraps other’s work, creating an evil dependency which is not easily rectified.  I am then bound by the wrapee’s software release schedule, as are those who choose to use my software.  Yes, I’m talking about ToscaWidgets.I wanted to break free from this paradigm, and I have taken initial steps in my ToscaWidget wrapper for Yahoo YUI.  Here comes a huge block of code, but don’t let it scare you, I will explain the problem it intends to solve:


class YUILinkMixin(Link):
    params = {'basename': '(string) basename for the given file.  if you want yuitest-min.js, the base is yuitest/yuitest',
              'suffix': '(string) "", min, beta-min, or beta.  Default is "min"',
              'version': '(string) select the yui version you would like to use. Default version is: '+__YUI_VERSION__,
              'external': '(boolean) default:False True if you would like to grab the file from YAHOO! instead of locally',
              'yui_url_base':'The base url for fetching the YUI library externally',
    }

    version = __YUI_VERSION__
    external = __DEFAULT_LINK_IS_EXTERNAL__
    yui_url_base = __YUI_URL_BASE__
    modname = "tw.yui"
    extension = 'js'
    default_suffix = __DEFAULT_SUFFIX__
    _suffix = ''

    def __init__(self, *args, **kw):
        super(Link, self).__init__(*args, **kw)
        if not self.is_external:
            modname = self.modname or self.__module__
            self.webdir, self.dirname, self.link = registry.register(
                modname, self.filename
                )
        if 'suffix' in kw:
            self.suffix = kw['suffix']
        else:
            self.suffix = self.default_suffix

    def _get_suffix(self):
        if self._suffix == '':
            return ''
        return '-'+self._suffix

    def _set_suffix(self, value):
        self._suffix = value

    suffix = property(_get_suffix, _set_suffix)

    @property
    def external_link(self):
        link = '/'.join((self.yui_url_base, self.version, 'build', self.basename+self.suffix+'.'+self.extension))
        #xxx:check for existance of this resource and choose -min -min-beta -debug or no suffix as alternatives.
        return link

    def _get_link(self):
        if self.is_external:
            return self.external_link
        return tw.framework.url(self._link or '')

    def _set_link(self, link):
        self._link = link

    link = property(_get_link, _set_link)

    def abspath(self, filename):
        return os.sep.join((os.path.dirname(__file__), filename))

    def try_filename(self, filename):
        abspath = self.abspath(filename)
        if os.path.exists(abspath):
            return filename
        return False

    @property
    def filename(self):
        #make basename windows/qnix compat
        basename = self.basename.replace('/', os.sep)
        basename = self.basename.replace('\\', os.sep)

        basename = os.sep.join(('static', self.version, 'build', basename))
        #try the default
        filename =  basename+self.suffix+'.'+self.extension
        if self.try_filename(filename):
            return filename

        #try '' if the default suffix is min
        if self.default_suffix == '':
            filename =  basename+self.suffix+'.'+self.extension
            if self.try_filename(filename):
                return filename

        #try min if the default suffix is ''
        if self.default_suffix == 'min':
            filename =  basename+'.'+self.extension
            if self.try_filename(filename):
                return filename

        #try debug
        filename =  basename+'-debug'+'.'+self.extension
        if self.try_filename(filename):
            return filename

        #try beta-min
        filename =  basename+'-beta-min'+'.'+self.extension
        if self.try_filename(filename):
            return filename

        #try beta
        filename =  basename+'-beta'+'.'+self.extension
        if self.try_filename(filename):
            return filename

        #try beta-debug
        filename =  basename+'-beta-debug'+'.'+self.extension
        if self.try_filename(filename):
            return filename
        return None

    @property
    def is_external(self):
        return self.external

class YUIJSLink(JSLink, YUILinkMixin):
    pass

class YUICSSLink(YUILinkMixin, CSSLink):
    extension = 'css'
 
So, the question is, how does using this code differ from using direct links to the YUI library, or using the ubiquitous JSLink Widget provided by ToscaWidgets, which is found in just about every other tw.js_wrapper available?
1) Testabliltiy - First and foremost, I wanted a way to test a new version of the library with my JS code to see if it would work, without having to change the wrapper at all.  A bit of a monkey-patch, but if you change the version of YUI that is fetched by altering one variable in the tw.yui library before doing subsequent imports.  If the current version is not available in the widget library, you can point it directly at yui's online library.  Run your tests, see what breaks, fix it, and you are now compatible with the new library.
2) Debugability - Synchronous with Testability, you can also set a flag for tw.yui to include all of the debug versions of the yui modules so you can dig down into the code using firebug if need be. (The default is minified)
3) Compatibility - Since you now can control what version of YUI you want to use, you can retro-fit an older project with Toscawidgets by downgrading the version of YUI that tw.yui is using.  You can also try out the newest version of YUI that may tw.yui is not yet using, and with the exception of new modules that have not been integrated into tw.yui, it should still work.
4) Maintainability - Since we now have the ability to swap versions, the maintainers of tw.yui can keep multiple versions of yui in the library, and deprecate them as they see fit.  This provides maintainability, as you would expect to see deprecation warnings about your WSGI Application's use of an out-of-date JS library.  This helps the whole process of knowing what libraries are current to what version, which can be a real bear, given all of the things we all must keep track of.
5) Producibility - The bottom line always comes down to whether or not you can pipe your development software up to production level efficiently.  (Is the code producible).  With the ability to test compatibility, and drop down to different versions of dependent libraries when compatibility is a concern, you will be able to keep all that works on your production server working, while bringing up new or updated functionality incrementally.  Keep in mind that the above code demonstrates the ability for system-level defaults of the javascript link widgets to be overridden for any particular widget instantiation.
These 5 items I call Production Engineering.  Basically, Production Engineering is developing a process which allows you to integrate working development code into your stead-fast production site, and allow you to back out software which may have mistakes.  A good software engineer realizes that people make mistakes, and there needs to be a way to buy some time so those mistakes can be fixed.  I believe that YUILinkMixin is a step in this direction, and I hope to extend it in the future to provide an even more robust toolset in line with Production Engineering.The complete source code for tw.yui is available at www.toscawidgets.org/hg .

Busy times with OSS

Friday, July 25th, 2008

I’ve not posted to this blog in over a month, mainly because I have been busy. Busy is a good thing I think. I have been helping clearwired get their newest web application off the ground, working on a number of screencasts, helping Mark with the latest batches of TG2 releases, learning about new and interesting OSS Python projects.

sphinx logo One of the more interesting things I have started to use with some frequency is Sphinx. Sphinx is a documentation system whichallows you to create webpages (among other things) with .rst files. It also grabs directly from your modules and inserts your docstrings (including your doctests.) It is great to have code which is not only documented, but also tested using nose. Look for a screencast from me in the near future on this one.

Two of the recent screencasts I have written show how to use virtualenv, PasteScript, and Nose. I go through a ground-up example showing how to create a virtualenv, a project package, and finally how to test that package and provide robustness with code coverage. The final screencast is about how to install TG2, which has become much easier in the advent of TG2’s first alpha release.

mountain gears TG2 is actually nearing it’s second alpha release. I think This is the best release yet. I spent some time moving DBSprockets to pep-8 compliance, and the two things TG2 depends on (tg.ext.silverplate and tgcrud) are now both using the newest release of DBSprockets. I also released basketweaver which allows you to create a simple local pypi made of static HTML files. Special thanks to Chris McDonough, who wrote the makeindex.py script. All I did was to fixed it up a little, and package using PasteScript, and provide a console_script for easy usage.

rum screenshot

Along with Sphinx, I have been trying to wrap my head around Rum, which is a new project to generate forms from database schema, much like DBSprockets. Although the internals of the system are somewhat mystifying, the API is squeaky clean, and in my mind what DBSprockets was eventually planned to be. The great news is that Alberto has done such a good job laying the groundwork for Rum I should be able to jump right in and apply lessons learned from DBSprockets. At this point it is safe to say that I will continue to maintain DBSprockets for bug fixes, but that the internals of it are going to be converted over to using Rum, before being deprecated altogether. DBSprockets had a great run, but it is time to move on and move forward with a superior design which promises to integrate so many WSGI technologies.

Speaking at Front Range Pythoneers

Tuesday, June 17th, 2008

Tomorrow Night I will be speaking about agile technologies with SQLAlchemy at the Front Range Pythoneers monthly meeting. I spent a few hours last night working out my presentation and creating a number of screencasts which show how to use tools like virtualenv, paster, and nosetests.  I also touch apon sqlalchemy, and how one would set up a test environment for their database schema.  Even if you don’t live in the Boulder/Denver area the information could be valuable to you, so I decided to set up a googlecode repository to store all of my tutorial-related materials.  It is called PythonTutorials.

My Blog’s Wordle

Tuesday, June 17th, 2008

wordle

http://wordle.net/

Namespacing with Setuptools

Monday, June 16th, 2008

Lately I am finding that it is worthwhile to separate projects into their own packages, but since they are all in the same domain, I want to have them share elements for importing purposes. Enter namespacing, which I believe is a little-used feature of setuptools that people should take a serious look at.

What is namspacing? Well, if you are familiar with creating packages, you know that often times they share similar traits, which means it would be nice to have sort of a global package where they all reside, but then you would not be able to install the components of said package independently. Lets say we have a solar system package, and inside it are elements for each planet. You might import from them like this:

from solarsystem.earth import echosystem

from solarsystem.venus import atmosphere

But what if you didn’t want to package simulations of all the planets, because sometimes you just want to install one or two of them at a time. Namespacing gives you a way of creating packages which are related to each other, but do not clash.

First off, you are going to need setuptools if you don’t already have it. Download the script here and run it with python. This will install the ubiquitous setuptools package which contains easy_install.

The easiest way I have found to create a namespace package is to use zopeskel, which provides a basic_namespace template for your project. First, we easy_install zopeskel:

easy_install zopeskel

Now we can list the templates that paster provides. Paster is a tool which provides a developer with an easy way to create templates for packages, as well as other useful utilities for python file management. (Paster is automatically installed by zopeskel)

$ paster create –list-templates
Available templates:
archetype: A Plone project that uses Archetypes
basic_namespace: A project with a namespace package
basic_package: A basic setuptools-enabled package
basic_zope: A Zope project
nested_namespace: A project with two nested namespaces.
paste_deploy: A web application deployed through paste.deploy
plone: A Plone project
plone2.5_buildout: A buildout for Plone 2.5 projects
plone2.5_theme: A Theme for Plone 2.5
plone2_theme: A Theme Product for Plone 2.1 & Plone 2.5
plone3_buildout: A buildout for Plone 3 projects
plone3_portlet: A Plone 3 portlet
plone3_theme: A Theme for Plone 3.0
plone_app: A Plone App project
plone_hosting: Plone hosting: buildout with ZEO and any Plone version
plone_pas: A Plone PAS project
recipe: A recipe project for zc.buildout
silva_buildout: A buildout for Silva projects
At the top of the list is basic_namespace, which we will be using. For example, lets make a solarsystem.mars package:

paster create -t basic_namespace solarsystem.mars

Paster will then prompt you with a series of questions, of which the first two are the most important:

Selected and implied templates:
ZopeSkel#basic_namespace A project with a namespace package

Variables:
egg: solarsystem.mars
package: solarsystemmars
project: solarsystem.mars
Enter namespace_package (Namespace package (like plone)) ['plone']: solarsystem
Enter package (The package contained namespace package (like example)) ['example']: mars

After you answer the rest of the questions, it will create a directory structure that looks something like:

solarsystem.mars/
|– README.txt
|– docs
| `– HISTORY.txt
|– setup.cfg
|– setup.py
|– solarsystem
| |– __init__.py
| `– mars
| `– __init__.py
|– solarsystem.mars.egg-info
| |– PKG-INFO
| |– SOURCES.txt
| |– dependency_links.txt
| |– entry_points.txt
| |– namespace_packages.txt
| |– not-zip-safe
| |– paster_plugins.txt
| |– requires.txt
| `– top_level.txt
`– zopeskel.txt

At which point, you are ready to create a development install of your project. Simply change to the directory:

cd solarsystem.mars

and:

python setup.py develop

Code for your new module would go in the solarsystem/mars/ folder, inside the new package. Any python you have installed this new package will
now be able to:

import solarsystem.mars

Namespacing is a great way to organize your work into digestible morsels, which can be installed one by one as needed by your perspective users. It is a great way to take advantage of all of the tools which have been created to make distribution and versioning easier.

Sprints, Vacation, Refreshment

Thursday, June 5th, 2008

It’s been a while since I have blogged for a few reasons. One, I took a vacation. No work, open source or otherwise for 11 days. I barely even checked my email. One thing that is great about living in Colorado: I don’t have to go anywhere on vacation, and my family will come to me! I took my sister up the First Flatiron, my dad fishing in Cheeseman Canyon, and all of us took a nice stroll through Chautauqua Park. We ate out almost every night and enjoyed catching up since I have moved 2000 miles away.

Previous to that, I managed to win a skirmish in the framework war at work, and spent an obscene amount of time (on and off the clock) bringing my first production-level TG2 site. This was a really fun project because my coworker and I were given the reigns and let loose on implementation. In 3 hours we had a working TG2 site with data in an EXT grid, with database schema expressed as a tree. In 3 weeks we had a complete reporting system (using EXT) with object-based security. We were also able to implement a file upload manager, and a select shuttle (for assigning groups to secure objects) thanks to the help of Sanjiv Singh, my GSoC protege. Thanks to all of you who have helped myself, and TG2 get off the ground.

One of the reasons I was so absent from the OSS community was that I was trying to wrap my head around what was going on with the EXT licensing, which changed under my feet as I was developing our in house app. The move from LGPL to GPL/Commercial was a shock to the community, and in my opinion based primarily on one person’s greed. My personal choice is to finish up whatever EXT support I have to do for our in-house application, and never look back at it again. I will be moving on to Dojo, and have advised my GSoC students and other people involved with TurboGears to do the same.

SilverPlate Demo site Now that I am back from vacation/new project hell, I have been able to release a new module for TurboGears, tg.ext.silverplate, which is a plugin for TG2 providing User Management and Profile pages which are customizable. This all fits under the TGTools domain, which has become a home for tg.ext.repoze.who (Authentication for TG2) and tg.ext.geo (An upcoming library for Geographical support in TG2). If you get a chance, you might want to check out the new TGTools googlecode site.

I also did a new release of tg.ext.repoze.who, which provides authentication/authorization to TG2. The only functionality I as able to contribute was a change to the name-spacing, as well as a full test of it’s functionality. Right now I am working on an LDAP bridge which will allow your TG2 site to authenticate against LDAP, and then dump you into the TurboGears Domain for all of the authorization stuff (groups, permissions, etc.) I should have this completed in a few days. Most of the work for tg.ext.repoze.who was done at the last world-wide WSGI-Turbogears sprint. It looks like TG is going to do a release in a few days.

This weekend I am headed to ABQ for some sprinting with clearwired on their next-generation web application. I am hoping this time around TG2 is mature enough in their eyes to take advantage of everything it has to offer, since they have currently chosen to work simply with Pylons as a framework. Either way, I will be working with some of the best people in the business, and we should be able to push TG foreward one way or another.