AS3 and Proxy

On January 24, 2008 in actionscript, as3, development, flash

In ActionScript 3, you can extend a class from the Proxy class to override the behavior of many language level operations, making it a valuable tool for advanced development. However, they are much slower than sealed classes, so be careful with their use when high performance is necessary.

Proxy allows you to override:

// function calls
foo.bar(1, 2)
=>
foo.callProperty('bar', 1, 2)

// property get
foo.bar
foo['bar']
=>
foo.getProperty('bar')

// property set
foo.bar = 123
foo['bar'] = 123
=>
foo.setProperty('bar', 123)

// property delete
delete foo.bar
delete foo['bar']
=>
foo.deleteProperty('bar')

// in operator
'bar' in foo
=>
foo.hasProperty('bar')

// descendant operator
foo..bar
=>
foo.getDescendants('bar')

Proxy also allows you to override the handling of for..in and for each..in loops, using the nextNameIndex, nextName, and nextValue methods. This for..in loop:

for (var key:String in foo) {
  trace(key);
}

on a proxy, is equivalent to:

var i:int = 0;
while (true) {
  var index:int = foo.nextNameIndex(i);
  if (index == 0)
    break;
  var key:String = foo.nextName(index);
  trace(key);
  i++;
}

Similarly, this for each..in loop:

for each (var value:* in foo) {
  trace(value);
}

on a proxy, is equivalent to:

var i:int = 0;
while (true) {
  var index:int = foo.nextNameIndex(i);
  if (index == 0)
    break;
  var value:* = foo.nextValue(index);
  trace(value);
  i++;
}

Here is an example stub class implementing these methods:

package {
  import flash.utils.Proxy;
  import flash.utils.flash_proxy;

  public class ExampleProxy extends Proxy {
    private var items:Array;

    public function ExampleProxy() {
      items = [];
    }

    override flash_proxy function deleteProperty(name:*):Boolean {
      return delete items[name];
    }

    override flash_proxy function getProperty(name:*):* {
      return items[name];
    }

    override flash_proxy function hasProperty(name:*):Boolean {
      return name in items;
    }

    override flash_proxy function nextNameIndex(index:int):int {
      if (index > items.length)
        return 0;
      return index + 1;
    }

    override flash_proxy function nextName(index:int):String {
      return String(index - 1);
    }

    override flash_proxy function nextValue(index:int):* {
      return items[index - 1];
    }
  }
}

Gmail IMAP and Thunderbird

On January 21, 2008 in tips

Google gives great instructions on how to get IMAP access setup in Thunderbird. But it can take some searching to work out all the kinks. Here are some tips to save you the digging I had to do:

Fixing the IMAP folders

Thunderbird tries to create its own folders for Sent Items, Drafts, and Trash, but it’s a bit cleaner if we just use Gmail’s.

To change Sent Items and Drafts, go to Tools -> Account Settings and go to Copies & Folders under your Gmail account. Choose Other for both, and browse to the appropriate [Gmail]/ folder.

To change Trash, go to Tools -> Options -> Advanced -> General and click Config Editor in the bottom right. Filter for mail.server.server. You’ll see mail.server.server1, mail.server.server2, etc. – one for each account you have.

Find the account you want to change, then right click and go to New -> String. Enter mail.server.server1.trash_folder_name where server1 is the server for your account. Press Ok and enter [Gmail]/Trash for the value.

Once you’ve setup your folders, you can log into Gmail and delete the [IMAP]/ filters that Thunderbird created.

Sorting emails by date and thread

If you want messages to be sorted like they are in Gmail, go to Tool -> Options -> Advanced -> General. Click Config Editor (bottom right) and filter for mailnews.thread_pane_column_unthreads. Double click the row to change it to false.

Then, back in the main window, go to the View -> Sort by menu and make sure Date, Descending, and Threaded are all selected.

Adding multiple Gmail accounts

Adding another Thunderbird account for each Gmail account you have works as expected except for one problem: by default, all of the accounts use a single SMTP server.

To add SMTP servers for additional Gmail accounts:

  1. Tools -> Account Settings
  2. Choose Outgoing Server (SMTP) (bottom of account list on the left)
  3. Click Add (right side)
  4. Enter a description (e.g. youremail@gmail.com)
  5. Enter smtp.gmail.com for Server Name
  6. Enter 587 for Port
  7. Check User name and Password
  8. Enter youremail@gmail.com for User Name (or youremail@yourdomain.com for Google Apps)
  9. Choose TLS for Use secure connection
  10. Click OK
  11. Choose the your Gmail account from the account list
  12. Select the new SMTP server from the Outgoing Server (SMTP) drop down list.

Reordering accounts

I added my accounts in a somewhat random order, and wanted to resort the way they appeared in my folder list. To do this go to Tools -> Options -> Advanced -> General. Click Config Editor (bottom right) and filter for mail.accountmanager.accounts. Double click the row to edit it.

You can swap the values to adjust the order. If you had: account1,account2,account3
and wanted account 2 to be first, change it to:
account2,account1,account3

Then click OK and restart Thunderbird.

Game Objects library

On September 15, 2007 in development, games, python

Game Objects is a collection of 2D and 3D maths classes, and algorithms for helping in the creation of games with Python.

Will McGugan’s Game Objects library has been invaluable for my dabblings in Python game development. It provides optimized objects for common graphics math (3D vector class, matrix class, etc.). The objects are flexible and framework independent, so you can use them with the platform of your choice, be it pygame, PyOpenGL, or DirectPython.

It’s a somewhat new project, and the documentation a bit sparse, but the library is pretty straightforward and he’s been updating it regularly.

Relevant links:

Vertex buffer objects in PyOpenGL

On August 31, 2007 in development, games, python

Decided to move some of my vertex array code over to ARB_vertex_buffer_object, to see if I could get a bit of a speed boost out of PyOpenGL. Much to my dismay, these functions don’t have the sexy extension wrappers I talked about before, so it was a bit of a chore to get it all working.

Here’s a little wrapper class I wrote to make things easier:

from OpenGL.GL import *
from OpenGL.raw import GL
from OpenGL.arrays import ArrayDatatype as ADT

class VertexBuffer(object):

  def __init__(self, data, usage):
    self.buffer = GL.GLuint(0)
    glGenBuffers(1, self.buffer)
    self.buffer = self.buffer.value
    glBindBuffer(GL_ARRAY_BUFFER_ARB, self.buffer)
    glBufferData(GL_ARRAY_BUFFER_ARB, ADT.arrayByteCount(data), \
                 ADT.voidDataPointer(data), usage)

  def __del__(self):
    glDeleteBuffers(1, GL.GLuint(self.buffer))

  def bind(self):
    glBindBuffer(GL_ARRAY_BUFFER_ARB, self.buffer)

  def bind_vertexes(self, size, type, stride=0):
    self.bind()
    glVertexPointer(size, type, stride, None)

  ... snipped for length ...

Download buffers.py.

So, how to use it? Let’s say you have a Python list with a bunch of vertexes with float x, y, and z components:

verts = [[x, y, z], [x, y, z], [x, y, z], ...]

You’ll have to use NumPy or an equivalent to convert it to a PyOpenGL compatible array:

import numpy
numpy_verts = numpy.array(verts, dtype=numpy.float32)

Create the VertexBuffer object with it:

buffer = VertexBuffer(numpy_verts, GL_STATIC_DRAW)

Use it in your day to day rendering:

glEnableClientState(GL_VERTEX_ARRAY)
buffer.bind_vertexes(3, GL_FLOAT)
glDrawElementsui(GL_TRIANGLES, indexes)

They’re not shown in the snippet, but I’ve also defined bind_colors, bind_edgeflags, bind_indexes, bind_normals, and bind_texcoords, as shortcuts for the rest of the GL array functions.

DRY your views with middleware

On August 11, 2007 in development, django, python

When I have Django URL patterns like:

urlpatterns = patterns('',
  (r'^(?P<foo_id>\w+)/$', 'myproject.myapp.views.show'),
  (r'^(?P<foo_id>\w+)/edit/$', 'myproject.myapp.views.edit'),
  (r'^(?P<foo_id>\w+)/delete/$', 'myproject.myapp.views.delete'),
)

I always end up with views like:

def show(self, foo_id):
  foo = get_object_or_404(Foo, id=foo_id)
  ...

def edit(self, foo_id):
  foo = get_object_or_404(Foo, id=foo_id)
  ...

def delete(self, foo_id):
  foo = get_object_or_404(Foo, id=foo_id)
  ...

Having the same few lines at the top of every function in makes me feel dirty. You can clean this up with a Middleware class, replacing foo_id with the actual object before calling the view.

myproject/myapp/middleware.py looks like this:

from django.shortcuts import get_object_or_404
from someapp.models import Foo

class FindObjects:
  def process_view(self, request, view_func, view_args, view_kwargs):
    if 'foo_id' in view_kwargs:
      view_kwargs['foo'] = get_object_or_404(Foo, id=view_kwargs['foo_id'])
      del view_kwargs['foo_id']

I include it in settings.py:

MIDDLEWARE_CLASSES = (
  ...
  'myproject.myapp.middleware.FindObjects',
)

And now my views look like this:

def show(request, foo):
  ... yay! do stuff with foo! ...

Very useful for views with many parameters, or views with multiple optional parameters. In one project, I have views which process data for three different situations: data in a metropolitan area, data in a city, or data in a city within a metro. My middleware for that looks like this:

from django.shortcuts import get_object_or_404
from phuce.metros.models import City, Metro

class FindObjects:
  def process_view(self, request, view_func, view_args, view_kwargs):
    city = metro = None
    if 'metro_link' in view_kwargs:
      metro = get_object_or_404(Metro, link=view_kwargs['metro_link'])
      del view_kwargs['metro_link']
      view_kwargs['metro'] = metro
    if 'city_link' in view_kwargs:
      if metro:
        city = get_object_or_404(City, metro=metro, \
                                 metro_link=view_kwargs['city_link'])
      else:
        city = get_object_or_404(City, link=view_kwargs['city_link'])
      del view_kwargs['city_link']
      view_kwargs['city'] = city

It’s much tidier without that monster in my views.

Good day, sir.

On August 09, 2007 in photography

Guardian of the Road Lizard.

Decal on an old abandoned truck I came across.

PyOpenGL's extension wrappers

On August 07, 2007 in development, games, python

Normally if you wanted to get access to an OpenGL extension, you’d have to do something like:

from ctypes import *    
from OpenGL import platform
gl = platform.OpenGL
glGetShaderiv = gl.glGetShaderiv
glGetShaderiv.argtypes = [c_int, c_int, POINTER(c_int)]

Gross. Luckily, PyOpenGL version 3.0.0a5 and later will automatically map ARB standard functions for you when they are available. Now all you have to do is:

from OpenGL.GL import *

And everything will be magically available to you, wrapped so you don’t have to use ctypes to create c_char_p or c_int variables to pass them.

Watch out, though! The functions won’t be mapped correctly if your display context hasn’t been created yet. Always make sure to import OpenGL after the pygame display has been initialized.

# first initialize pygame
import pygame
from pygame.locals import *
pygame.init()
pygame.display.set_mode((800, 600), OPENGL | DOUBLEBUF)

# now you can import it
from OpenGL.GL import *

I would love to know how to manually tell PyOpenGL to re-map everything after initializing pygame, though. I don’t like having to reposition the import like that. Nathan Gray has a deep reload replacement for the reload builtin, which might work, but I’m not sure if that’s the best solution to this problem…

Field labels in templates

On July 25, 2007 in development, django, python

There’s no way in Django (that I’ve found) to render a field’s name in a template. This means you end up with <th>Field Name</th> all over your templates. Why hello there, DRY violation!

The fields are stored in model._meta.fields, but templates don’t allow you to access variables which start with an underscore. I’ve got two little utility functions I wrote for myself to generate a dict of labels I can use in my templates:

def get_labels_for(model, cap=True, esc=True):
  from django.template.defaultfilters import capfirst
  from django.utils.html import escape
  labels = {}
  for field in model._meta.fields:
    label = field.verbose_name
    if cap:
      label = capfirst(label)
    if esc:
      label = escape(label)
    labels[field.name] = label
  return labels

def with_labels(context, cap=True, esc=True):
  from django.db.models import Model
  result = context.copy()
  for k, v in context.iteritems():
    if isinstance(v, Model):
      result[k + '_labels'] = get_labels_for(v, cap, esc)
    elif hasattr(v, '__getitem__') and len(v) > 0:
      if isinstance(v[0], Model):
        result[k + '_labels'] = get_labels_for(v[0], cap, esc)
  return result

The parameters:

  • model can be a model class or a model instance.
  • If cap is True, the first letter of each label will be capitalized.
  • If esc is True, the labels will be escaped for HTML.

So, in your view:

def some_view(request, foo_id):
  foo = get_object_or_404(Foo, id=foo_id)
  context = {'foo': foo, 'foo_labels': get_labels_for(foo)}
  return render_to_response('foo.html', context)

And in your template:

{{ foo_labels.bar }}: {{ foo.bar }}

with_labels works the same way, except you can just surround your context with it:

def some_view(request, foo_id):
  foo = get_object_or_404(Foo, id=foo_id)
  bars = Bars.objects.all()
  context = {'foo': foo, 'bars': bars}
  return render_to_response('foo.html', with_labels(context))

It will detect the models and lists of models in the context and add foo_labels and bars_labels to the context.

Random filenames

On July 23, 2007 in development, python, ruby

In Python:

import os.path, random, string
def random_filename(chars=string.hexchars, length=16, prefix='', suffix='', \
                    verify=True, attempts=10):
  for attempt in range(attempts):
    filename = ''.join([random.choice(chars) for i in range(length)])
    filename = prefix + filename + suffix
    if not verify or not os.path.exists(filename):
      return filename

>>> random_filename()
'DC53e02B08eF47e9'
>>> random_filename(chars='hi', length=32)
'hhhihihhhiiihhhihhiiiiiihhhhiihh'
>>> random_filename(prefix='username', suffix='.txt')
'username7dbd29aBdD25BeB9.txt'

# returns None if it can't find a filename
>>> open('xxx', 'w').close()
>>> str(random_filename(chars='x', length=3))
'None'

In Ruby:

def random_filename(opts={})
  opts = {:chars => ('0'..'9').to_a + ('A'..'F').to_a + ('a'..'f').to_a,
          :length => 16, :prefix => '', :suffix => '',
          :verify => true, :attempts => 10}.merge(opts)
  opts[:attempts].times do
    filename = ''
    opts[:length].times { filename << opts[:chars][rand(opts[:chars].size)] }
    filename = opts[:prefix] + filename + opts[:suffix]
    return filename unless opts[:verify] && File.exists?(filename)
  end
  nil
end

Private by default

On July 22, 2007 in development, django, python

When most pages in a site require authentication, decorating all the views with @login_required can be annoying. You can reverse the default behavior by creating a custom middleware class:

import urllib
from django.conf import settings
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.http import HttpResponseRedirect

def allow_anonymous(view_func):
  view_func.allow_anonymous = True
  return view_func

class RequireLogin:
  def process_view(self, request, view_func, view_args, view_kwargs):
    if request.path != settings.LOGIN_URL and \
      not request.user.is_authenticated() and \
      not getattr(view_func, 'allow_anonymous', False):
      url = '%s?%s=%s' % (settings.LOGIN_URL, REDIRECT_FIELD_NAME, \
                          urllib.quote(request.get_full_path()))
      return HttpResponseRedirect(url)

That’s an ugly block of code but it’s not too complex. allow_anonymous is a function decorator, like login_required. It just tags the function to tell the middleware that authentication isn’t required. The RequireLogin class verifies that the user is logged in. If not, and if the function is not decorated with allow_anonymous, it redirects to settings.LOGIN_URL.

So put that code in a file in your project – let’s say, yourproject/yourapp/middleware.py. Then open settings.py and add "yourproject.yourapp.middleware.RequireLogin" to MIDDLEWARE_CLASSES. This tells Django about your new middleware class, and RequireLogin.process_view will be called any time a view is about to be rendered.

Now you can use it in your view:

from yourproject.yourapp.middleware import allow_anonymous

def some_private_view(request):
  # won't be accessible unless user is logged in
  return HttpResponse('Hello, user!')

@allow_anonymous
def some_public_view(request):
  return HttpResponse('Hello, world!')

If all is working correctly, some_private_view should ask for a login, but some_public_view will allow viewing without it.

Update: I’ve updated the code to fix a bug when using django.contrib.auth.views.login for your login view. As you can’t mark this view function with @allow_anonymous, it would infinitely redirect back to it. Oops! Thanks for pointing it out, Phil.