Hello, my name is Joshua Inkenbrandt and I live in Kansas City, Missouri with my wife and two kids. I'm a Mac guy. I'm a Python guy.

My goal is to make cool stuff that's fun and easy to use.

Only showing Posts with topic Programming X

June 24, 2010

Tornado Tip

I actually discovered this nice little feature when I was up working late one night. When you pass a dictionary into self.write(), it will automatically be JSON encoded and will set the Content-Type header for you.

import tornado.web
import tornado.escape

# Long version
class HelloWorldHandler(tornado.web.RequestHandler):
    def get(self):
        response = dict(error=False, message="Hello World")
        self.set_header('Content-Type', 'text/javascript')
        self.write(tornado.escape.json_encode(response))

# Short version
class HelloWorldHandler(tornado.web.RequestHandler):
    def get(self):
        response = dict(error=False, message="Hello World")
        self.write(response)

April 12, 2010

Tornado's Templates

Tornado is awesome — its documentation at this point isn't. So here's my little contribution to make a great web framework a little easier to develop in.

First things first, Tornado's templates aren't sandboxed like Django's. Meaning it converts your templates into Python code and then executes them with a given context. And there's a benefit in rendering templates as evaluated Python code. Speed. Aside from being fast, I've personally found Tornado's templating syntax to be much easier to write in than Django's, though they are very similar.

But there's also a downside. Templates in Tornado make it possible to do almost anything, including accessing your database, deleting your files, terminating your webserver's instance, etc. These things can actually can be done in Django if you use a custom filter or tag, but straight out of the box, Django protects you from your templates. So a redundant and some-what-obvious word of warning: use discretion when writing your templates in Tornado.

Basic Output

1 Hello, {{ current_user.name }}

Basic Logic

 1 {% if not current_user %}
 2     You're not logged in!
 3 {% elif current_user and curent_user.is_admin %}
 4     Good day, sir!
 5 {% else %}
 6     Howdy!
 7 {% end %}
 8 
 9 {% for link in links %}
10     <a href="{{ link.href }}">{{ link.title }}</a>
11 {% end %}
12 
13 {% set i = 10 %}
14 {% while i %}
15     Item {{ i }}
16     {% set i -= 1 %}
17 {% end %}
18 
19 {% try %}
20     {{ undeclared_var }}
21 {% except NameError, e %}
22     {{ e }}
23 {% end %}

Inheritance

 1 <!-- base.html Template -->
 2 <body>
 3     <div id="main">
 4     {% block main %}
 5         You'll see me if the 'main' block isn't overridden
 6     {% end %}
 7 </body>
 8 
 9 <!-- home.html Template -->
10 {% extends "base.html" %}
11 {% block main %}
12     Now you see me!
13 {% end %}

Comments

1 {% comment "I'm a comment" %}

Includes

1 {% include "other_template.html" %}

Imports

1 {% import os %}
2 {% import sys %}

Setting Variables

1 {% set DEBUG = True %}
2 {% set BASEPATH = os.getcwd() %}

Applying a function to a block

1 {% apply escape %}
2 <h1>Hello World</h1>
3 {% end %}
4 output:  <h1>Hello World</h1>
5 
6 {% apply base64.b64encode %}
7 Base64 Encode Me!
8 {% end %}
9 output: CkJhc2U2NCBFbmNvZGUgTWUhCg==

Caveats

Because the templates are executed as Python code, they follow the same explicit rules as Python. For instance, if you try to access a variable that doesn't exist in scope {{ myvar }} , you'll get a NameError. If you're used to using Django or Jinja, this might throw you off. Also note that every closing block tag is always just {% end %} .

There's a lot more you can do with templates when they're integrated with Tornado's tornado.web.RequestHandler. I would recommend, if you haven't already, giving Tornado a try. It's a perfect combination of simplicity and power.

March 05, 2010

A Completely Unfair Comparison

Many of my colleagues don't understand why I complain as often as I do about ActionScript 3. Sure it's got its quirks and issues, but is it really all that bad? Well, to anyone who has done any significant work with a highly dynamic language like Python or Ruby, it is. I understand that the comparison between a Domain Specific Language like ActionScript 3 and a general purpose language like Python or Ruby isn't really a fair one. That's not the point, though. The point is to see what it would look like to use a more dynamic language (In this case - Python) to accomplish what you would normally have to do in AS3.

In AS3, the Object, Array, String and Date classes all lack any sort of useful API when compared to Python.

Let's start with the Object:

 1 // ActionScript 3
 2 
 3 var object:Object = {key1:'value1', key2:'value2'};
 4 
 5 // Get the keys of the object and store them in an array
 6 var keys:Array = [];
 7 for (var key:String in object)
 8     keys.push(key);
 9 
10 // Get all the values of the object and store them in an array
11 var values:Array = [];
12 for (var key:String in object)
13     values.push(object[key]);
14 
15 // Test to see if the object contains a particular value
16 var containsValue:Boolean = false;
17 for (var key:String in object)
18     if (object[key] == 'value2') containsValue = true;
19 
20 // Add new values to the object
21 var newObject:Object = {key3:'value3'};
22 for (var key:String in newObject)
23     object[key] = newObject[key];
24 
25 // Get the length of the object
26 var objectLength:Number = 0;
27 for (var key:String in object)
28     objectLength++;

Let's do the same in Python:

 1 # Python
 2 
 3 obj = {"key1":"value1", "key2":"value2"}
 4 
 5 # Get all the keys of an object (or dictionary in Python)
 6 keys = obj.keys()
 7 
 8 # Get all the values of a dictionary}
 9 values = obj.values()
10 
11 # Test to see if the dict contains a particular value
12 contains_value = 'value2' in obj.values()
13 
14 # Add new values to the dict
15 obj.update({"key3":"value3"})
16 
17 # Get the length of the object
18 object_length = len(obj)

The lack of built-in support for rudimentary methods really stands out. At least to me.

Then the Array

 1 // ActionScript 3
 2 
 3 var array:Array = ['one', 'two', 'three', 'five'];
 4 
 5 // Looping over values
 6 for each (var value:String in array)
 7     trace(value);
 8 
 9 // Looping over indexes
10 for (var i:Number = 0, l:Number = array.length; i < l; i++)
11     trace('index = ' + i, 'value = ' + array[i]);
12 
13 // Slicing
14 var firstHalf:Array = array.slice(0, 2);
15 var lastHalf:Array = array.slice(2);
16 
17 // Seeing if a value exists in array
18 var valueExists:Boolean = array.indexOf('two') != -1;
19 
20 // Concatenate
21 var newArray:Array = array.concat(['five', 'six']);
22 
23 // Get the number of times a value repeats itself in the array
24 var numValues:Number = 0;
25 for each (var value:String in array)
26     if (value == 'five') numValues++;

And in Python

 1 # Python
 2 # In Python an array is called a list
 3 
 4 array = ['one', 'two', 'three', 'five']
 5 
 6 # Looping over values
 7 for value in array:
 8     print value
 9 
10 # Looping over indexes
11 for i, value in enumerate(array):
12     print "index = %s value = %s" % (i, value)
13 
14 # Slicing
15 first_half = array[:2]
16 last_half = array[2:]
17 
18 # Seeing if a value exists in array
19 value_exists = 'two' in array
20 
21 # Concatenate
22 new_array = array + ['five', 'six']
23 
24 # Get the number of times a value repeats itself in the array
25 num_values = array.count('five');

I don't have much of a beef with the Array in AS3. It's pretty evenly matched when it comes to built in methods compared to Python.

Let's look at the String.

 1 // ActionScript 3
 2 
 3 var string:String = "Hello World";
 4 
 5 // Test to see how may 'l' characters are in the string
 6 var num:Number = 0;
 7 for each (var char:String in string.split(''))
 8     if (char == 'l') num++;
 9 
10 // Capitalize
11 var cap:String = string.substr(0, 1).toUpperCase() + string.substr(1);
12 
13 // Make it title case
14 var title:String = "";
15 var prev:String = " ";
16 for each (var char:String in string) {
17     if (prev == " ") char.toUpperCase();
18     title += char;
19     prev += char;
20 }
21 
22 // See if it starts with "Hell"
23 var startsWith:Boolean = string.substr(0, 3) == "Hell";
24 
25 // See if it ends with "rld"
26 var endsWith:Boolean = string.substr(string.length-4) == "rld";
27 
28 // Remove white space before and after
29 string = "  Hello World  ";
30 var cleanString:String = string.replace(/^\s+/, "").replace(/\s+$/, "");

And in Python we do:

 1 # Python
 2 
 3 string = "Hello World"
 4 
 5 # Test to see how may 'l' characters are in the string
 6 num = string.count("l")
 7 
 8 # Capitalize
 9 cap = string.capitalize()
10 
11 # Make it title case
12 title = string.title()
13 
14 # See if it starts with "Hell"
15 starts_with = string.startswith("Hell")
16 
17 # See if it ends with "rld"
18 ends_with = string.endswith("rld")
19 
20 # Remove white space before and after
21 string = "  Hello World  ";
22 clean_string = string.strip();

Conclusion

These examples express my own laziness, in a way. But it's not because I'm too lazy to write a utility class that simplifies the aforementioned examples. It's because I don't feel like i should have to. You can't blame Flash for following ECMAScript. It's a great scripting language, but what makes ECMAScript great is that it's a prototypical language. What bothers me about ActionScript 3 is that it has moved away from being a prototypical language.

Again, the purpose behind this post isn't to prove the superiority of one language over the other. It's like comparing apples to oranges... I just prefer apples.