Test static resources in Django tests

June 2, 2011
3 comments Django

At Mozilla we use jingo-minify to bundle static resources such as .js and .css files. It's not a perfect solution but it's got some great benefits. One of them is that you need to know exactly which static resources you need in a template and because things are bundled you don't need to care too much about what files it originally consisted of. For example "jquery-1.6.2.js" + "common.js" + "jquery.cookies.js" can become "bundles/core.js"

A drawback of this is if you forget to compress and prepare all assets (using the compress_assets management command in jingo-minify) is that you break your site with missing static resources. So how to test for this?

Truncated! Read the rest by clicking the link below.

A script tag's type in HTML5

May 10, 2011
4 comments JavaScript

If you look at html5boilerplate.com they never use any type on their <script> tags. Hmm... but is there more to it?

If you don't specify a type, the default becomes "text/javascript" but according to RFC4329 the "text/javascript" MIME type is obsolete in favor of "application/javascript".

If the default MIME type for a <script> tag thus becomes either "text/javascript" or "application/javascript" is there any sensible browser on this green earth that would not translate a piece of inline Javascript code as, exactly that; Javascript? Probably not.

What about <script> tags with a src attribute? Does the type matter?

I read the spec a couple of times and it feels like reading legalese but it ultimately says: the value of the type tag must be that of the body of the script tag.

So, what happens if you embed a javascript file with a mismatching type? Let's see:

Truncated! Read the rest by clicking the link below.

maxlength_countdown() - a useful jQuery plugin for showing characters left

May 1, 2011
6 comments JavaScript

If people find this useful I might turn it into a proper jQuery plugin and publish it.

Without further ado; here's the demo

What it does is that for all input fields that have a maxlength="nnn" it shows a counter to the right that increases in opacity as it reaches the maximum. You can generally start it like this:


$('input[maxlength]').maxlength_countdown();

Since the plugin "hard codes" the count down expression in English you can override it easily like this:


$('input[name="message"]').maxlength_countdown(function (count, max) {
   return count + " (max: " + max + ")";
});

What do you think? Is it useful? Does it make sense?

Mocking DBRefs in Mongoose and nodeunit

April 14, 2011
0 comments JavaScript, MongoDB

Because this took me a long time to figure out I thought I'd share it with people in case other people get stuck on the same problem.

The problem is that Mongoose doesn't support DBRefs. A DBRef is just a little sub structure with a two keys: $ref and $id where $id is an ObjectId instance. Here's what it might look like on the mongodb shell:


> db.questions.findOne();
{
       "_id" : ObjectId("4d64322a6da68156b8000001"),
       "author" : {
               "$ref" : "users",
               "$id" : ObjectId("4d584fb86da681668b000000")
       },
       "text" : "Foo?",
       ...
       "answer" : "Bar"
       "genre" : {
               "$ref" : "question_genres",
               "$id" : ObjectId("4d64322a6da68156b8000000")
       }
}

DBRefs are very convenient because various wrappers on drivers can do automatic cross-fetching based on this. For example, with MongoKit I can do this:


for question in db.Question.find():
   print question.author.first_name

If we didn't have DBRefs you'd have to do this:


for question in db.Question.find():
   author = db.Authors.findOne({'_id': question.author})
   print author.first_name

Truncated! Read the rest by clicking the link below.

TornadoGists.org - launched and ready!

April 6, 2011
1 comment Python, Tornado

Today Felinx Lee and I launched TornadoGists.org which is a site for discussing gists related to Tornado (python web framework open sourced by Facebook).

Everyone in the Tornado community seems to solve similar problems in different ways. Oftentimes, these solutions are just a couple of lines or so and not something you can really turn into a full package with setup.py and everything.

Sharing a snippet of code is a great way to a) help other people and b) to get feedback on your solutions.

The goal is to make it a very open and active project with lots of contributors. I'll be accepting and reviewing all forks but hopefully control will be opened up to all Tornado developers. Also, since the code is quite generic to any open source project Felinx and I might one day port this to rubygists.org or lispgists.org or something like that. After all, Github does all the heavy lifting and we just wrap it up nicely.

Strange socket related error with supervisord

April 5, 2011
7 comments Linux

This took me a long time to figure out so I thought I'd share.

Basically, I'm a newbie supervisor administrator and I was setting up a new config and I kept getting these errors:


# supervisord -n
2011-04-04 17:25:11,700 CRIT Set uid to user 1000
2011-04-04 17:25:11,700 WARN Included extra file "/etc/supervisor/conf.d/gkc.conf" during parsing
Error: Cannot open an HTTP server: socket.error reported errno.ENOENT (2)
For help, use /usr/local/bin/supervisord -h

The reason was that in my config I had the line:


[unix_http_server]
file=/var/lib/tornado/run/gkc.sock

but the directory /var/lib/tornado/run didn't exist. Creating that solved the problem.

Lesson learned from all this is that when specifying locations of .sock files always make sure the directories exist and that the current user can write to them.

Bash tip of the day: ff

March 25, 2011
2 comments Linux

This is helping me sooo much that it would a crime not to share it. It's actually nothing fancy, just a very convenient thing that I've learned to get used to. ff is an executable script I use to find files in a git repository. Goes like this:


$ ff list
templates/operations/network-packing-list.html
templates/sales/list_orders.html
$ ff venue
templates/venues/venues-by-special.html
templates/venues/venues.html
templatetags/venue_extras.py
templatetags/venues_by_network_extras.py
tests/test_venues.py

It makes it easy to super quickly search for added files without having to use the slow find command which would also otherwise find backup files and other junk that isn't checked in.

To install it, create a file called ~/bin/ff and make it executable:


$ chmod +x ~/bin/ff

Then type this code in:


#!/usr/bin/python
import sys, os
args = sys.argv[1:]
i = False
if '-i' in args:
   i = True
   args.remove('-i')
pattern = args[-1]
extra_args = ''
if len(args) > 1:
   extra_args = ' '.join(args[:-1])
param = i and "-i" or ""
cmd = "git ls-files | grep %s %s '%s'" % (param, extra_args, pattern)
os.system(cmd)

My AWS CloudFront bill

March 23, 2011
1 comment This site

I've put all the static resources behind this site now on AWS CloudFront For example this: http://static.peterbe.com/misc_/Peterbecom/home/grey_face.1282513695.png

This site doesn't really have much traffic. About 50,000 pageviews per month. The bill for the last month: $0.55

I think I can afford that :)