Django Dash 2010 winners

I was shocked, yesterday, to discover that my team had won the 2010 Django Dash for our buildout management project, Great Big Crane. Competition was extremely fierce, and there are a fair number of projects that I felt would be contenders for first place. My personal goal was to move upward from the fifth place we were awarded last year, and I would have been completely satisfied with third.

While Jason and I obviously did a terrific job of keeping our backend code elegant and organized, I think the major difference between our project and the competition was Phil’s amazing styling. His enthusiasm and attention to detail throughout the project turned a neat project into a work of art.

A lot of really interesting projects came out of the Dash. It’s amazing how much fifty teams can accomplish in 48 hours. I hope all the participants had as much fun as I did!

  • Share/Save/Bookmark

Get your head out of the clouds: Local web applications

I spent this weekend with two friends crazy enough to join me in a 48 hour coding sprint for the Django Dash. We competed in the dash last year and placed 5th. Our goal was to move up in the rankings this year (competition is stiff, wish us luck!). Our team had the highest number of commits, but I can’t say how many of them can be justified as quality commits… especially since we keep track of our TODO file inside the git repository!

This year, we created a project called Great Big Crane. (I don’t know why we called it this.) The code is stored on Github, and we set up a splash page at greatbigcrane.com. We don’t have a live demo for reasons I’ll get into shortly.

This project’s primary purpose is to help managing buildouts for Python projects, most especially Django projects. It helps take care of some of the confusing boilerplate in buildout configuration. It also allows one click access to common commands like running bootstrap or buildout, syncdb, manage.py, or migrate, and running the test suite associated with a buildout. It does most of these actions as jobs in the background, and pops up a notification when it completes. It even keeps track of the results of the latest test suite run so you can see at a glance which of your projects are failing their tests.

One of the most intriguing things this application does is open a text editor, such as gvim, to edit a buildout if you need more control than our interface provides. It does this be queuing a job that executes the text editor command on the server.

Wait, What? It can be a bit creepy when clicking a button in a web application fires up an arbitrary program on your computer.

This entire app is designed to run on localhost. It’s set up for developers to manage their own projects. It doesn’t support authentication (this is why we don’t have a live demo), and the server has full access to the local filesystem. It’s meant to support your local IDE, not to provide an online IDE. The entire app is therefore super fast (no network delay), and switching from it to my text editor to several terminals became quite normal as I was developing on it (yes, the buildout for Great Big Crane runs just fine from inside Great Big Crane ;) .

So yes, you’re expected to run this web app locally. Why would anybody want to do this? Is it a sensible thing to do?

The alternative to what we’ve done here would be to code the whole thing up as a GUI application of some sort. I have experience with most of the Python GUI toolkits, and I can’t say that I “enjoy” working in any of them. I’m not sure I enjoy working in HTML either, but I do a lot of it. HTML 5 with CSS 3 is certainly a powerful and reasonable alternative to modern graphical toolkits.

I’ve been coding HTML for so long that I don’t know what the learning curve is for it, but I’m definitely more comfortable working with it than I am with TK, QT, GTK, or WxWidgets, all of which take a long time to learn how to code properly. Possibly I’m just stagnating, but I think I’d prefer to develop my next “desktop” app as a webapp intended to run locally, rather than study these toolkits again. Indeed, because I think I’d prefer to do that, I started coding my last project in PyQT, just to fight the stagnation tendency. PyQT is an incredibly sensible toolkit, after you have learned how to make sense of it, but it’s not as sensible as the new web standards. Another advantage is that if you ever decide you want to make the app network enabled, you’re already running an app server, and using standard web technologies to push it to the cloud.

So my gut feeling at this point is that yes, it is sensible to design “traditional” desktop apps using HTML 5, CSS, and javascript for the interface, and your choice of webserver and web framework for the backend. Perhaps it’s not any more sensible than using a GUI toolkit, but it’s certainly not insane.

If it makes sense to replace local desktop apps with a local server, does it also make sense to replace web applications with a local system?

I’m not a huge fan of web applications because they are slow for me. I have a good connection (by Canadian standards, which aren’t high…). Yet Gmail is slower than Thunderbird, Freshbooks is too slow for me to justify paying for it, and github, while fascinating, is also slow compared to local access. The only webapp I have tested that I consider responsive is Remember The Milk, a popular todo list. I’m not certain what they do to make it so responsive, but I suspect Google Gears or HTML 5 localstorage must be involved.

Local storage. I’ve written about this before (I must be getting repetitive). My idea then was that offline enabled webapps are just as responsive as desktop apps. But the current available paradigm, using HTML5 localstorage, requires a lot of overhead normally involving manual syncing between the browser data and the server. What if I was running the app locally instead? Then I could just design it as a “normal” web app, without having to put extra thought into designing and maintaining local storage in the browser. It would be super responsive when I access it from my computer. More interestingly, it would also be available from remote computers. If I accessed it across my LAN using another laptop or my phone’s wifi, it would still be acceptably responsive. And if I happen to need access from the library or my friend’s computer, I can log in remotely, and still have approximately the same level of responsiveness that I currently get by logging into a server in the cloud.

This isn’t a new idea. It’s been presented as a “gain control of your own data” alternative to the privacy and control fears that Google, Facebook, and Apple (among others) have been creating. (<a href="http://www.h-online.com/open/features/Interview-Eben-Moglen-Freedom-vs-the-Cloud-Log-955421.html"this Is a nice discussion). There are a lot of clear advantages of moving data local, but there are also disadvantages. The nice thing about cloud storage is not having to worry about data backup. The “access anywhere” paradigm is nice, too, although that is not ruled out with running a home webserver. Zero install and end users not having to think about dependencies is also nice.

Overall, I’m finding more and more reasons to bring our apps home, where we have control of them. Such cycles are common in the technology industry. Dumb terminals mainframes. Personal computers. Business networks. The Internet. The cloud. Off-board video/On-board video. Network cards? On-board nic. Hardware modems or Software modems. Personally, I think the cycle away from the cloud is just beginning. I think the company that finally conquers Google will be doing it by giving you back control of your data. I’ve never been totally comfortable with the whole web application idea (as a user — they’re fine to develop!). I’m still trying to identify what my reasons are, but in the meantime, we experimented with the idea by developing Great Big Crane as a local web application.

  • Share/Save/Bookmark

ArchCon 2010: A tale of beer

Arch devsI don’t normally write public journal-like entries, but I’d like to describe my experience at ArchCon as an advertisement to attract more attendees next year!

As co-organizer of the conference, I felt a lot of pressure for it to go well. People had paid registration fees to attend, as well as their travel arrangements and accommodation costs. I wanted it to be worth the time, effort, and money they spent to attend.

I think it was. I feel quite confident that no-one was disappointed.

My trip started a week before the conference. Dieter came over from Belgium around the same time as me. We did some touring around Toronto and down to Niagara Falls, and I had the dubious pleasure of introducing him to Canada’s own special recipe: poutine.

On Wednesday, the day before the conference, my best friend, fellow arch user, and ex-developer, Jason Chu flew in from Victoria, BC. I navigated my way to Humber College, where the conference was hosted and where we were rooming together on campus. Our room very closely resembled a prison cell with cement walls, floors and ceilings. We each got a private bedroom; mine was especially private (and prison-like) as my magnetic key card tended to need frequent resetting.

We met up with Ricardo Alvez who gave us a tour of the college and classrooms and then drove us to a nearby Mr. Greek for supper. We were all thoroughly entertained and swapped a variety of stories, information, and ideas.

Ricardo dropped us off at our dorm where we impatiently waited for our third roommate, Dan McGee (veteran pacman hacker, patch rejector, and expert freelancer). Jason and Dan had never met before, but they quickly became old friends and we spent the weekend insulting each other just like old friends who have far too much respect for each other always do.

We failed in our first mission of Archcon: Find a pub near campus. Dan and Jason were less than impress when we settled for Tim Horton’s (A Canadian coffee/donut chain) instead. Conference consensus is that, wherever Archcon 2011 is held, it must be in proximity to multiple pubs. No beer that night, but it wasn’t for lack of trying!

We went to bed slightly too late, but got up in time. I had meant to be at the conference early and get set up before anyone arrived, but there were already several attendees in the room when I walked in. People seemed a bit nervous and reluctant to allow me to draw them into conversation, but this didn’t last. People became very animated and everyone had something to contribute.

I haven’t presented anything since I was in school, and I have always been an awful presenter with massive public speaking anxiety. So I was surprised, as I set up my introductory speech, to find I felt relaxed and comfortable and was looking forward to the talk. I don’t think the talk was terribly well done, but I was happy with it, and most importantly, enjoyed it. The best part was, having my talk over first, I was able to enjoy the rest of the conference completely anxiety free!

We all experienced a fair amount of anxiety to begin with, though, as wireless was not immediately available. We had an ethernet port in the room, but no wireless routers. This was eventually resolved when Jason set his laptop up as an access point.

We had arranged scheduled talks in one room with various versions of free form discussion in a second room. With the small number of attendees, the second room didn’t get much use on day one, although a small collection of us got together for an informal bug squashing. I had intended to run this in parallel with an online bug squashing in IRC, but I had trouble getting into IRC and had previously thoroughly forgotten to advertise the session! I wrote a patch for an archweb bug, but I’m sure Dan will be rejecting it.

The conference was catered with pastries and drinks at breaks, and burgers, hotdogs, and way too much salad at lunch.

I am writing this as I upload and encode videos, so I won’t describe individual talks. The presenters were all game and presented well. The talks really made the conference, and I think a lot of enthusiasm for Arch development was generated among the participants, even (or especially) those of us who have basically left the community.

Day one ended with a trip downtown to find food and, more importantly, beer. I’d say about half the attendees went out, and I’m pretty confident fun was had by all. If laughter is the best medicine, we should all be very healthy for some time to come. Matt and Jason’s argument about…. well, I’m not sure what they were arguing about, but it was entertaining to watch them argue.

Day two started about 15 minutes late. Most people showed up surprisingly close to on time in spite of the late night. Coffee was consumed. After the scheduled talks wrapped up, several attendees presented “lightning talks” (5-8 minutes on whatever topic makes you happy). These forced a lot of variety into a short amount of time and were quite entertaining.

I was sad that we missed out on the development sprints. These were scheduled to occur in parallel with the last talk, but I think we were all a bit too tired and decided to watch the talk instead. I had in my mind we’d have time to do development after the lightning talks, but instead we ended the conference early. Some people left, having to catch planes, buses, or other commitments, but a large group of us stuck together. Dan and Jason coerced Kevin into chauffeuring them through a beer run while the rest of us borrowed Dan’s disc to play a game of three on three ultimate. Given Toronto’s humidity, we were soaked with sweat in short order. I still managed to cause grievous injury to my right thumb, though. It’s still hard to type and even harder to text as I write this.

Once Dan, Jason, and Kevin returned, and Jason had fixed a problem with his company’s web servers, we headed over to a Chinese buffet for dinner. The group kept shrinking as people left.

Next, the beer was consumed in our prison-like dorm. The number of beer-consumers was disproportionate to the amount of available beer, and we ran out quickly. Alex and Eric showed up shortly after all beer cans were empty. We had to switch to alternate forms of entertainment, and rotated between exchanging friendly insults and compliments, modifying and discussing playlists, discussing the history and future of Arch Linux, and planning ArchCon2011. Jason was repeatedly asked why he wasn’t carrying his Nexus one. Apparently this question annoys him.

That was the official end of ArchCon, but not for me. Jason, Dan and I spent Saturday touring Toronto in the rain. I didn’t go up the CN tower, but they had a wireless lounge that allowed me to write a python script to create the archcon image thumbnails page you’ve seen. I wrote it on my android cell phone over SSH with my injured thumb.

Dieter and a local friend of his met us at the bottom of the CN tower and we made our way to the Cloak and Dagger for more beers. We were all hungry, but didn’t realize that their kitchen was closed on Saturday. Jason and I grabbed a pair of pizzas which disappeared to quickly. So Dieter and I picked up a couple more. Loui showed up and further Arch discussion ensued with, of course, an adequate consumption of beer. I’m told it was one of the best place to get beer in the city.

I wouldn’t know. I don’t drink.

  • Share/Save/Bookmark

Upcoming Schwag Shipping Delays

I’d like to thank all my Arch Schwag customers for being the best schwag customers ever! Sales are steady and brisk, and I’ve been able to donate several hundred dollars to the Arch Linux project this year. Laptop stickers are, by far, the most popular item, but handbooks, t-shirts, lanyards, and pens are also well-liked. The occasional laptop bag and piece of jewelery are also ordered.

In a few days, I will be headed to Toronto for a vacation, tai chi training, and ArchCon. This means that orders for any items I ship personally will not be shipping until the end of the month. I apologize for the inconvenience, but I’m the only person involved in these items. If you are making an order and planning to move, it may be wise to have your items shipped to an alternate permanent address.

The items affected include laptop stickers, case badges, pens, and lanyards. Orders from the Zazzle store will not be affected, nor will orders for the Arch Linux Handbook. Orders for laptop bags and jewellery will likely only suffer minor delays, as I simply have to contact the people who create them; it will depend how slow I am to deal with my e-mails.

  • Share/Save/Bookmark

Schwag Shipping

Canada Post recently raised its shipping rates. Again. I think it’s the third time in a year, and the increase was substantial. I have considered their rates to be unfair for quite some time, and have tended to keep my shipping rates lower than my actual costs (handling fees, such as envelopes, printer ink, and tape are other costs I face). However, I had to raise the rates on most of my products today in order to cover more of the costs. Some of my more recent shipments have cost me more than the amount I was making on the products themselves.

As a government-run corporation, I believe Canada Post should be making more of an effort to keep it’s rates low and facilitate the moving of mail across this rather large country. I find it insulting that it costs so much for me to ship items to my Canadian clients. I understand the costs associated with international shipments, but with the unique size, geography, and climate in this country (it’s a tough place to live), I feel it is very important to have the infrastructure for getting both people (it is costing my $1000 for return flights to ArchCon in Toronto and back. I can fly to Vegas with 5 nights included for half that.) and parcels across the country as cheaply, efficiently, and easily as possible.

That said, most of my schwag customers are not located in Canada, and I am taking even bigger hits on my shipments to those customers. I have investigated some alternatives, such as travelling to the US to mail orders in bulk, but less often, but USPS has also been steadily raising their rates, and the savings to my customers wouldn’t cover the gas to get down there, the hassle at the border, or the added delays.

I anticipate reduced sales from these raised prices, and I apologize to those who feel it is too expensive to order Arch Schwag products. I will continue investigating cheaper forms of logistics, and hopefully I will be able to reduce the rates someday!

  • Share/Save/Bookmark

Validate as you type in javascript

This is a common task, but has several facets that are easy to miss. I needed an input element that would validate as you type to ensure that an integer value was always entered. This was easily done by doing a replace against a regular expression, linked to the keyup event:

function validate_number(event) {
    this.value = this.value.replace([/[^0-9]/g,'');
}
 
$('jquery selector').keyup(validate_number);

This works fine provided the user is typing at the end of the box. The problem is that if the user has clicked in the middle of the number, aiming to insert a new digit, each time this.value is set, the cursor is moved to the end of the box, regardless of whether or not a valid character was entered. This happens on every keypress. That is bad.

The solution is to save and reset the selection range, as follows:

function validate_number(event) {
    if (this.value.match(/[^.0-9]/g)) {
        var start = this.selectionStart-1;
        var end = this.selectionEnd-1;
        this.value = this.value.replace(/[^.0-9]/g,'');
        this.setSelectionRange(start, end);
    }
}

I haven’t found any situations where this code doesn’t work, but there is one other caveat: pasting. If the user pastes a non-numeric value into the field without issuing a keypress (ie: using the right click–> paste menu), the value will not be validated. I haven’t found a way to stop this at the point when the value is pasted, but I’ve found it sufficient to additionally call the validation function when the textbox loses focus:

$('jquery selector').keyup(validate_number).blur(validate_number);

A variation of this code can be used to validate most inputs as the user types; a regular expression that matches whitespace can remove whitespace, phone numbers would look for digits and hyphens, decimal numbers would additionally search for a period, etc.

  • Share/Save/Bookmark

Packaging django management commands: Not Zip Safe

I had a devil of a time sorting this out; it must be documented in other places, but on the off chance that this information is useful to anyone, I’m posting it here.

I wrote a django app that had a custom management command in it. When I ran this app in my development environment, it ran fine. But when I deployed it from Pypi as an egg, the command mysteriously disappeared. Django simply did not see it.

Django not seeing management commands is a common problem for me, it seems like I always have to say “please” in just the right tone of voice before my custom management commands will work. This problem, however, was a new one for me.

I ended up exploring the Django sources and discovered, eventually, that the imp builtin was unable to find anything inside a zipped egg. This struck me as odd, so I did some research on a nifty tool I discovered (over a decade ago) called Google.

I came across this message, which basically says that Django and Django apps are “flat-out not zip-safe and probably never will be”, making specific reference to custom management commands.

Then I had to do more research to figure out how to mark my app as not zip safe. I ended up switching my setup.py for the app from distutils.core to setuptools and added a zip_safe=False argument to the setup call.

In addition, for my future and perpetual sanity, I discovered that buildout can accept an unzip=true command to ALWAYS unzip eggs. I placed this under the [buildout] section in my buildout.cfg.

  • Share/Save/Bookmark

Converting a Django project for zc.buildout

Jacob Kaplan-Moss has written an article on using zc.buildout to develop a django application. My goal is slightly different: I want to deploy an entire django project, with numerous dependencies, using zc.buildout. The documentation seems scarce, so I’m trying to keep track of each step as I go, in the hopes that it may be useful to someone someday.

I have an existing Django project that I’m having trouble deploying and sharing with other developers. It’s located in a private github repository. So my goal is not only to manage a Django project, but to manage an already mature project. This is, of course, harder than starting from scratch.

I do my development on Arch Linux, which is currently running Python 2.6 (and 3.1, but Django isn’t supported, so I’m using 2.6 for this project). I have git version 1.7.1, and my project is using Django version 1.2.1.

Since I didn’t know what I was doing, I started by doing some exploring. I created an empty directory and ran:

wget http://svn.zope.org/*checkout*/zc.buildout/trunk/bootstrap/bootstrap.py

to install the buildout bootstrap. I then created a very simple buildout.cfg file based on the djangorecipe example:

[buildout]
parts = django
eggs = ipython
 
[django]
recipe = djangorecipe
version = 1.2.1
eggs = ${buildout:eggs}
project = my_project

I then ran:

python bootstrap.py
./bin/buildout

Suddenly, my directory containing only two files (bootstrap.py and buildout.cfg) looked like this:

bin
buildout.cfg
downloads
my_project
bootstrap.py
develop-eggs
eggs
parts

Jacob’s article has an excellent description of all these files. The main question for me was “where does my source go?” This example shows that the project source code goes in my_project. Djangorecipe had created the following structure in that directory:

development.py
__init__.py
media
production.py
settings.py
templates
urls.py

The development.py and production.py files both have from my_project.settings import * calls, and then customize some variables. My habit has always been to have a localsettings.py in my .gitignore and include from localsettings.py import * in my main settings.py. For my project I had to decide whether to stick with my old habits, or modify my setup to be parallel to the djangorecipe version.

I see that djangorecipe has a way to select the settings to use for a given buildout, but if buildout.cfg is under version control, wouldn’t that make selecting settings a pain? And if each developer has a different database setup, would we require a different settings module for each developer? In my experience, it is better to do things the way the examples in the documentation say it should be done, because they know what they’re doing and I don’t. But in this case, I decided to keep my layout as is. I can always change it later.

The thing I wanted to learn from that experiment was where my source goes; apparently it goes in a folder with my project’s name at the same level as buildout.cfg and bootstrap.py. Looks like I’m going to have to move my code around in my project’s version control.

First I checked out a new branch, because that is the thing to do in git. Specifically because I want it to be easy to go back to the status quo if I decide, halfway through the process, that buildout is a pain to configure.

git checkout -b buildout

The first thing I want to do is move all my files into a new subdirectory with my project’s name, so buildout can have the top of the git tree for it’s own files:

mkdir my_project
git mv -k !(my_project) my_project
mv localsettings.py my_project
rm *.pyc
git commit

The git mv command essentially says “move anything that isn’t my_project into my_project“. The -k switch says “just ignore it if it isn’t under version control.” This left my localsettings.py and a few .pyc files in the main directory, since those files are in .gitignore, so I cleaned those up manually. Finally, I committed the changes, so the move happened in one place.

Now it’s time to start creating a new buildout, this time in the version controlled directory. I ran the wget command to get bootstrap.py, and I copied the buildout.cfg from my exploration directory. Then I ran the bootstrap and bin/buildout commands to see what happened. It did the same thing before, except for providing a django: Skipping creating of project: my_project since it exists. That’s what I wanted. Running git status showed several patterns that needed to be added to my .gitignore:

.installed.cfg
bin
develop-eggs
downloads
eggs
parts

I also had to change the .gitignore file to ignore my_project/static/uploads instead of just static/uploads.

At this point, I decided to commit bootstrap.py and buildout.cfg:

git add bootstrap.py buildout.cfg
git commit

Now, I know I’m missing dozens of dependencies, but I wanted to see what happens if I run bin/django. My understanding is that this is supposed to be a wrapper similar to management.py, but using the buildout’s django environment. It failed, telling me that the development settings.py file didn’t exist. I modified the buildout.cfg to add settings = settings to the django recipe. Then I ran bin/django again, and nothing had changed.

Whenever you change buildout.cfg, you have to also run bin/buildout to create the new environment (rant: I hate compile steps!).

I was worried that my custom management commands (in my case, for py.test testing, and running south migrations) would not show up, but there they were, listed in the help output that bin/django provided. This is especially surprising, since I have not installed south inside the buildout yet! It appears that bin/django is a drop-in replacement for manage.py.

Next, I ran bin/django shell expecting to enter dependency hell. Not yet! Instead, I got the error “no module named my_project.settings”. Looking at the bin/django script, it is trying to prepend the project name to the project. I have a habit of not including an __init__.py in my project directory, preferring to think of a django project as a collection of apps, rather than an independent project. I don’t want to write from my_project.my_app import something, because then the apps are no longer reusable. In my world, the project is not a package. Apparently, djangorecipe thinks it is. So touch my_project/__init__.py had to happen, since I definitely don’t want to start hacking the recipe at this point!

Now I have “no module named ” errors for each of my INSTALLED_APPS. Because I list my apps as “x” instead of “myproject.x”. To fix this, I added extra-paths = my_project, which inserts the project directory into the path.

Then I ran bin/django shell and bin/django runserver only to discover that everything was working! Apparently my buildout had not installed to a private environment, and was still accessing the default site-packages on my system. Not quite what I wanted. I thought zc.buildout created an isolated environment, much like virtualenv, only portable across systems. My mistake.

zc.buildout does not create an isolated sandboxed environment by default.

I had to do a lot of google searching to come to this conclusion. There are many statements out there that suggest that zc.buildout can and does create an isolated environment, but none of them turned out to be true. zc.buildout is all about reproducibility, while virtualenv is about isolation They are not competing products, and the ideal environment uses both of them.

So I removed all the temp files and directories (including the hidden .installed.cfg) that buildout had created for me and started over to install them to a virtualenv:

virtualenv -p python2.6 --no-site-packages .
source bin/activate
python bootstrap.py
bin/buildout

I temporarily removed IPython from the eggs because it was refusing to download. The server must be down. This time, when I run the bin/django shell, I get a proper dependency error for psycopg2. Looks like I’m finally on the right track. I also had to add several directories virtualenv had created to my .gitignore.

Before buildout, I had a rather complicated dependencies.sh file that installed all my dependencies using a combination of easy_install, git checkout, hg checkout, etc. I started with the easy_install stuff; stuff that can be installed from Pypi. I created a new eggs part in my buildout. The entire file now looked like this:

[buildout]
parts = eggs django
 
[eggs]
recipe = zc.recipe.egg
interpreter = python
eggs =
    psycopg2
    south==0.7
    django-attachments
    pil==1.1.7
    Markdown
    recaptcha-client
    django-registration-paypal
    python-dateutil
 
[django]
settings = settings
recipe = djangorecipe
version = 1.2.1
eggs = ${eggs:eggs}
project = my_project
extra-paths = my_project

Trying to run bin/buildout now causes a “Text file busy” error. At this point, I’m seriously considering that buildout is more of a pain than a help. It’s poorly documented and broken (some might say poorly documented IS broken). And I know I have an even harder task coming up when I have to patch a git clone.

But, I’m obstinate and I persevered. Google was quick to confirm my hypothesis that virtualenv and buildout were both trying to access the “bin/python” file. The solution was to change the interpreter = python line in my recipe; I called the buildout interpreter” py”.

This time, when I ran bin/django shell I got an error pertaining to a module that needs to be installed from git. Time to look for a git recipe! Here’s how it eventually looked:

[django-mailer]
recipe = zerokspot.recipe.git
repository = git://github.com/jtauber/django-mailer.git
as_egg = True

I also had to add django-mailer to my parts in the [buildout] section, and arranged the [django] extra-paths section as follows:

extra-paths =
    ${buildout:directory}/my_project
    ${buildout:directory}/parts/django-mailer

I had a second git repository to apply, and this one was messy because the code on the project was not working and my dependencies.sh was applying a patch to it. I was considering whether I had to hack the git recipe to support applying patches when I realized a much simpler solution was to fork it on github. So I did that, applied my patch, and rejoiced at how simple it was.

Finally, I had to install an app from a mercurial repository (because we can’t all use the One True DVCS, can we?) I found MercurialRecipe, but no examples as to how to use it. It’s not terribly difficult:

[django-registration]
recipe = mercurialrecipe
repository = http://bitbucket.org/ubernostrum/django-registration

With all my dependencies set up, I was finally able to run bin/django shell without any errors.

Now I have to figure out how to make this thing work in production, but that’s another post. I hope it works flawlessly on my co-developer’s Mac. Hopefully the pain will be less painful than the old pain. This was a huge amount of work, several hours went into it, and I won’t know for a while if it was worth it.

  • Share/Save/Bookmark

Django Registration Paypal Backend

One of my clients needed integration with Paypal for his site. The django-paypal module is great for this sort, but it didn’t quite suit our needs because we wanted to disallow account logins until payment had been collected. We had been using django-registration to support registration, and I decided to stick with it. The development version of django-registration has support for different registration backends. The default version sends an e-mail to verify the user’s e-mail address before they can get in. A simpler backend included with the project allows direct registrations with no verification. We needed a backend that required, not only e-mail address verification, but also confirmation that a paypal payment had been made.

And so, django-registration-paypal was born:

http://pypi.python.org/pypi/django-registration-paypal/0.1.1
http://github.com/buchuki/django-registration-paypal

It is, like all my first releases, pretty rough around the edges, and contains at least one glaring security hole. But it’s out in the wild now, and patches, as always, are welcome.

  • Share/Save/Bookmark

Google Wave Re-evaluated

Several months ago, I posted an evaluation of Google Wave that wasn’t too positive.

Since then, the Wave interface has had several minor, but very important improvements that make it much more pleasant to use. If there were more people using it, I would definitely view it as a viable alternative to e-mail and possibly even instant messaging. It still needs some serious usability engineering (it will never become mainstream unless they overcome the modal editing, for one thing), but I believe Google’s wave client has promise.

However, I no longer view wave as an alternative e-mail and IM. I’ve been considering it lately, as a replacement for HTTP. That’s right, the entire web. The current version of the web is highly interactive and realtime. HTTP was not designed for this. It was designed as a set of static resources intertwined with links. Then Javascript came along, and AJAX. The latest is a host of HTTP push technologies such as Comet.

These technologies allow the server to send information to the client without the client having to request it. A clever hack keeps an HTTP connection open for long periods of time so incoming data can be pushed across it without the client having to make a new request. Does this sound brilliant or what?

You’re doing it wrong! If our applications are now highly interactive systems that need to both push and pull data to and from the server, HTTP is not the protocol to use. In my opinion, these push technologies are messy. No, not just messy, but dirty, filthy hacks intended to force a system to be used in a way that is the opposite of what was designed.

No, if we are developing web applications these days that require two-way communication pipes (and we are), we need a two-way protocol.

Enter Google Wave. The Wave federation protocol is exactly that: a set of extensions to the two-way XMPP protocol. Wave is not a terrific solution for hosting static content, but static content is a rare commodity these days. Wave provides an ideal platform for most of the common activities people interact with on a daily basis. It already gives us chat, wiki, document editing, and e-mail like functionality for free. With a bit of effort, it can give us a blogging type of functionality (with comments), using public waves.

A couple of simple robots could replace Twitter. Wave doesn’t have support for “following” a user. You have to be added to specific waves. However, it would be trivial to write a robot that a user adds to any waves they want to have subscribed followers added to. “Retweet” functionality should also be fairly easy to implement. And this would be implemented on a distributed system, so there would be no more of those extremely irritating “twitter over capacity” messages.

Wave even solves the mighty facebook privacy issue. Only share your wave with those people you explicitly want to view it. Current policy is to post your ideas on Facebook public to all your friends. But a massive paradigm shift is occurring, as more and more people accidentally include their parents, employers, or spouse in conversations that were meant for other audiences. People are clamoring for Facebook to make it trivial to SELECT who we share information with. Guess what? Wave already does this.

In spite of all this, I’m still not on the Wave bandwagon. I don’t insist or even suggest that anyone should start using. The current browser-based client is complicated and intimidating and has a large learning curve. In today’s world, people expect things to be as easy to use as Google Search or Twitter. Wave is not. The currently available wave client is more complicated than e-mail or instant messaging. It’s not going to take off.

I believe there is potential for simpler clients to be designed. I’m finally understanding why Google has focused on solidifying the wave server and protocol, rather than improving the public facing client. They are the kind of technologies we should be looking to in the future, not HTTP. Google Wave may never take over the world, but at some point, something will have to replace the static HTTP protocol. Maybe wave, maybe HTTP 2.0 will have extensions for two way communication, maybe an entirely new protocol yet.

  • Share/Save/Bookmark