Chicken Wing Software

Developing ideas on developing.
Page style (CSS):

Weblog posts

How I edit Django templates

March 21st, 2008 by Eddie Sullivan

NOTE: This post is pretty old, and I no longer use mmm-mode for Django template editing. This post and this post are still accurate, though.

Every programmer has their favorite editor and mode of working. Some people have more than one. For example, I use Microsoft Visual Studio when editing .NET code, DrScheme for editing Scheme code, and XEmacs for pretty much everything else.

This post is about how I use XEmacs for editing Django template files, in the hopes that others may find this useful.

The "Other" One True Editor

It's rare that people will get passionate about something as pedestrian as a way of editing plain text, but the brief history of the internet is awash with flamewars and heated discussions with titles like "Emacs vs. XEmacs," "Emacs vs vi," and so on. I'm not about to go into the relative merits, but the fact that certain editors pop up time and time again in these debates must mean there is something special about them.

Early on in my college education I started using Emacs because it was all that was available on the school's servers. (Well, that or vi, but vi was and still is black-magic to me.) I got over the learning curve, and now I'm hooked.

At some point, I switched from Emacs to XEmacs, for reasons I can't remember. At the time, it had some feature which was to me essential. That reason no longer applies, but neither have I had a reason to switch back. These tips may apply even if you use GNU Emacs, but they've only been tested in XEmacs.

My current setup is Xemacs 21.4 (patch 20), running on Windows XP. *gasp!* Yes, I use Windows for Django development. Shocking, I know. I have my reasons. In any case, these tips should work equally well with XEmacs on other platforms.

Multiple Major Modes

I won't include a full XEmacs tutorial here, since there is already plenty of info on the web about it. The key point is that there is a "major mode" for each programming environment. There is a Python mode, a Java mode, and so on. Django templates tend to combine more than one language in a file, so that's when the mmm library comes in handy. It stands for "multiple major modes," and it turns out to be just exactly what we need. We can have html-mode for the HTML parts, JavaScript-mode for the JavaScript parts, css-mode for embedded CSS, and python-mode for the Django template filters and tags.

Which HTML mode?

As often happens in the world of Free Software, there are several options to choose from when setting up HTML editing in XEmacs.

  • html-mode. This has the fullest support for HTML parsing and validation. The problem is, when dealing with templates, the HTMl will often not validate, so all kinds of error messages show up.
  • sgml-mode. This is a more general mode for SGML (of which XML and HTML 4 are subsets).
  • xml-mode. SGML mode specialized for XML.
  • hm--html-mode. I have no idea what the HM stands for, but this is a lightweight HTML mode, with basic syntax highlighting and indentation.

I use html-mode for full-fledged HTML documents, and hm--html-mode for templates. So that XEMacs can tell the difference, I use the suffix ".tmpl" for template files.

One problem

I did run into some problems getting mmm-mode to work with XEmacs. It turns out the version of mmm-mode that is distributed with the XEmacs package system is ancient - from 2001. I had to download the newer version of mmm-mode and unzip it into my site-packages directory.

How it looks

Here's a screenshot of me editing an example Django template (borrowed from my beta-registration Django app). I've chosen fairly bright colors to make the syntax highlighting more obvious, but that's all customizable. Notice how the Django tags and variables are easy to find in the file. (Click on the image for a larger size.)

My initialization file

Here is the subset of my ~/.xemacs/init.el file dealing with setting up mmm-mode for XEmacs. I hope someone finds this useful. Let me know if you do, or if you encounter problems.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; CSS-Mode
(autoload 'css-mode "css-mode" "Mode for editing CSS files" t)
(add-to-list 'auto-mode-alist '("\\.css\\'" . css-mode))
(setq cssm-indent-function #'cssm-c-style-indenter)
(setq cssm-indent-level '2)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Use hm--html-mode for files that end in .tmpl (Django templates)
(add-to-list 'auto-mode-alist '("\\.tmpl\\'" . hm--html-mode))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Multiple Major Modes.
(require 'mmm-vars)
(require 'mmm-mode)
(require 'mmm-sample)
(setq mmm-global-mode 'maybe)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Custom MMM classes for Django templates
(mmm-add-classes
 '((my-django-expr
    :submode python-mode
    :face mmm-declaration-submode-face
    :front "{%"
    :back "%}"
    :include-front t
    :include-back t)))

(mmm-add-classes
 '((my-django-var
    :submode python
    :face mmm-output-submode-face
    :front "{{"
    :back "}}"
    :include-front t
    :include-back t)))

(mmm-add-mode-ext-class nil "\\.tmpl\\'" 'embedded-css)
(mmm-add-mode-ext-class nil "\\.tmpl\\'" 'my-django-var)
(mmm-add-mode-ext-class nil "\\.tmpl\\'" 'my-django-expr)
(mmm-add-mode-ext-class nil "\\.tmpl\\'" 'html-js)

;; Use different colors for different sub-modes.
(setq mmm-submode-decoration-level 2)
;; Make the code submode a little more readable.
(set-face-background 'mmm-code-submode-face "#EEEEFF")

When to use ToArray()

February 11th, 2008 by Eddie Sullivan

Some thoughts on when to return a List<> object and when to return an array in C#.

The analogy: strings

Many times in C#, a function that needs to build a string from constituent parts will use a StringBuilder internally, and then on the last line of the function call ToString() on the StringBuilder object. This is because strings in C# are immutable. That is, once they are set then can never be changed. Code that looks like it is changing a string in place is usually actually allocating a new string to hold the new value. Obviously, for a function that builds a string incrementally by constantly appending to it, this can lead to lots of reallocation, slowing down performance.

Here's an example of how it's normally done:

    public string GimmeString(int num)
    {
        StringBuilder sb = new StringBuilder("Initiating countdown: ");

        for (int i = num; i > 0; i--)
        {
            sb.Append(string.Format("{0}...", i));
        }
        sb.Append("Blastoff!\n");

        return sb.ToString();
    }
    

This is a pretty obvious design pattern. It's rare you would want to return the StringBuilder object itself, so almost always it is converted to a string before returning. The problem gets trickier, however, when we try to use a similar design pattern for arrays.

Arrays

Arrays in C# are not immutable, at least not in the way strings are. It could be said they are "partially immutable" (my own made-up term). You can swap out elements in the array as much as you like, but the array's length is fixed. Therefore, if you need to build up an array from constituent parts, it makes sense to use a List<> object for doing the work.

The analogy then becomes, in SAT terms:

StringBuilder : string :: List<> : array

The question then becomes whether or not to call ToArray() on the List<> before returning it. In this case, the answer's not as obvious. Let's examine the pros and cons of each approach:

Reasons to call ToArray()

  • If the returned value is not meant to be modified, returning it as an array makes that fact a bit clearer.
  • If the caller is expected to perform many non-sequential accesses to the data, there can be a performance benefit to an array over a List<>.
  • If you know you will need to pass the returned value to a third-party function that expects an array.
  • Compatibility with calling functions that need to work with .NET version 1 or 1.1. These versions don't have the List<> type (or any generic types, for that matter).

Reasons not to call ToArray()

  • If the caller ever does need to add or remove elements, a List<> is absolutely required.
  • The performance benefits are not necessarily guaranteed, especially if the caller is accessing the data in a sequential fashion. There is also the additional step of converting from List<> to array, which takes processing time.
  • The caller can always convert the list to an array themselves.

ToArray() or not ToArray()? That is the question.

Based on these points, it seems to make the most sense as a general rule to simply return the List<> object directly, rather than converting it to an array before returning. Let me know if you disagree.

Here's an example:

    // A contrived example. Similar to Python's "range" function, but only
    // supports positive step.
    public List<int> GimmeInts(int start, int end, int step)
    {
        List<int> ret = new List<int>();

        for (int i = start; i < end; i += step)
        {
            ret.Add(i);
        }
        // Here you could have:
        // return ret.ToArray();
        return ret;
    }
    

What’s wrong with hotels

February 8th, 2008 by Eddie Sullivan
Anybody who needs to stay in hotels often knows there are certain areas where they could all do better. I tend to look at everything with an eye towards what could be improved. Here are some random thoughts on how hotels could be better. Some of these ideas are a bit far-fetched, but hey, that's why I'm writing a weblog, not a manifesto.

More pricing logic

It sometimes seems like the cheaper a hotel is, the more services it provides. I've stayed in a broad range of hotels, from top of the line luxury suites to eight-cot-to-a-room hostels. Strangely, there are some areas where the lesser quality hotels actually do better. Why is it that when I pay $40 per night for a small family-run inn, there is personalized service and free wi-fi in every room, but in a hotel that charges $375 per night there is either no wi-fi available or it costs $20 extra? What are we actually getting for the higher price? Why do cheap hotels provide breakfast but expensive hotels don't? It's backwards.

Cleanliness

After seeing watching a news report about hotel cleanliness issues, I've been a little bit paranoid about sanitation in hotels. A couple idea:
Get rid of the carpet
Carpeted floors are notoriously hard to clean. I don't want to think about what kind of dirtiness people can leave on carpets that doesn't get picked up by a vacuum cleaner. Get rid of the carpeted floor. Replace it with hardwoods, or if that's too expensive, a synthetic material designed to not be too cold on our toes.
Auto-magically clean
Have you seen those coin-operated public restrooms in public cities that actually clean themselves after each use? Why can't we refine this technology and use it for hotel bathrooms? When the maid comes in, he or she removes all the towels and paper products, closes the bathroom door, and presses a button. Instantly, the whole bathroom is sprayed with disinfecting detergent from a nozzle in the ceiling, rinsed, then dried with high-speed air jets. Put the bed on hydraulic lifts to make it easy to clean underneath. Instead of just layering a blanket on top of a sheet, use a large pillow-case-like wrapper for the whole blanket. Design the quilt with drawstrings to make changing the blanket case easy. There is nothing worse than tossing around at night and waking to realize the sheet has slid off the bed and you're now face-to-face with someone else's potential filth.

Conveniences

This should be obvious, but: free wi-fi. For everyone. Everywhere. Provide an easy to use central control panel for things like the alarm clock, the thermostat, maybe even ordering room-service. Every hotel alarm clock has a different interface, leaving guests with no confidence they will actually wake up on time. Digital thermostats for the showers. It takes me forever to get the temperature just right in an unfamiliar shower. I want to be able to just turn a dial or press a button for the exact temperature I need and let the electronics do the rest.

And more

The more I think, the more ideas I come up with. I know most of these will never happen, but it can't hurt to dream, can it? Feel free to add any ideas using the comment link below.

Programming for Not-so-dummies

January 30th, 2008 by Eddie Sullivan

Somebody posted a reply to my last post about Django's autoescaping mechanism. (They were too cowardly to post on my site, so they posted it at reddit.com.) The person said something like, "you shouldn't trust yourself to remember to escape your own variables." Oh, heaven forbid I trust myself to be a good programmer! That really got me thinking about the recent trends towards designing frameworks, APIs, even languages for mediocre programmers. We are sacrificing speed, simplicity and efficiency to make common bugs less common, trying to design away the mistakes inexpensive and poorly-trained computer scientists make.

Now, of course when I say "recent trends," I should acknowledge that this type of thinking has been around for decades. It was first truly popularized with the introduction of Java. Some people forget to free memory, so add garbage collection. Some people forget to bounds-check arrays, so make that automatic. Ooh, pointers are scary! Let's get rid of them. We can't allow our outsourced foreign coders direct access to memory!

Good training, along with working for nearly a decade as an embedded software engineer, has taught me good programming habits. I've learned to be conscious of memory leaks, to always check return values, to program defensively, to bounds-check. I've created software for shipping products in such low-level and "unprotected" languages as C++, C, and even Assembly. I've written production code within less than the memory space required for a Java byte-code interpreter. And of course, I'm not alone in this. There is a large subset of software developers who had to learn to program carefully, due to constraints out of their control. These types of good programming habits carry over into whatever platform or language is used.

I feel a lot of the new safety-net style approaches are simply enabling poor programmers to work on increasingly sophisticated projects. To get back to the example from my last post, Django is a wonderful tool. You can program a sophisticated database-centered multi-user web application without even knowing how to spell SQL. Django's recent addition of autoescaping, and more importantly, the enabling of autoescaping globally by default, is yet another example of API-design for the lowest common denominator. (I should note that I love Django. It saves me writing a lot of redundant code and provides a lot of things for free that I would otherwise need to write from scratch, so I don't mean to pick on Django here. It just happened to be the catalyst for this discussion.)

It's not all bad

I know I'm starting to sound like an old curmudgeon. "In my day, we didn't have variables, we just had to carry around rocks to count!" I'm not that old, really. And I'm certainly not advocating we go back to the days before garbage collection and bounds checking. Especially given the potential security ramifications of memory-management bugs, these things are especially important. I just want to urge caution before binding developers in a straitjacket. Rather than trying to design away all potential bugs at the level of the language or API, emphasize and facilitate good programming and testing practices. I've never once bought a For Dummies book, and I never will. Please don't force me to use a For Dummies application framework.

Escaping autoescape in Django

January 28th, 2008 by Eddie Sullivan
I've been pleased with the Django web-application platform. Programming in Python is fun and fast, and Django provides many things for free that would be a lot of work to program from scratch. I've also enjoyed developing with the "bleeding edge" development version of Django. I like being able to use the latest features before they make it into the official releases. Whenever I stumble across what I think is a bug in Django, the first thing I do is "svn update" in my Subversion checkout, and most of the time the bug has already been fixed in the trunk. Recently, however, a major change in the Django development version has caused all of my projects to stop working! Needless to say, this was a bit frustrating. The change was the addition of "autoescaping" in Django.

What it is

The autoescape setting, referred to in the Django documentation as Automatic HTML escaping, means that any variable inserted into a rendered template gets the function django.utils.html.escape called on it. You can see what this function does in the file trunk/django/utils/html.py, but essentially as of today's code base it applies the following set of substitutions:
your_string.replace('&', '&amp;').replace('<', '&lt;'). \
    replace('>', '&gt;').replace('"', '').replace("'", '''))
(Ironically, I had a lot of trouble getting that code fragment to look right, due to Wordpress's own autoescaping, which I ended up disabling altogether. Aaarrgh!) On the surface, this seems like a useful feature. It seems to have been done to "idiot-proof" the template language, and to prevent cross-site-scripting vulnerabilities in case there is user-generated text stored in variables and the programmer forgets to call the appropriate escape function.

The problems

In general, I hate this kind of stuff. I can't stand it when Microsoft Word capitalizes the first letter of my sentences. If I wanted a capital letter, I would have held down the shift key! I hate it when the rear defroster in my car shuts off automatically after 30 minutes. Hello! Just because 30 minutes have passed doesn't mean it's not still raining out; doesn't mean I don't still live in New England! Essentially, I don't like it when machines think they are smarter than I am, or when they try to do what I mean, rather than what I say. If I had wanted to escape my variables, I would have escaped them. That's the first problem. This would not be such a big issue if it weren't for the second problem: this new disruptive feature is turned on by default, with no easy way to disable it across the board. I have a lot of programatically generated HTML and Javascript code contained in template variables. As you can imagine: instant breakage!

How to turn it off

The Django documentation does not have much good information on how to disable this new feature. Supposedly you can add the text "|safe" to every variable reference. Obviously this is impractical on even the smallest sites. Supposedly also, you can surround every template with "{% autoescape off %}" and "{% autoescape end %}" . This could be a viable option for a small site, but for someone who has to manage several sites, each with a large number of templates, this quickly becomes cumbersome. The documentation claims that the "autoescape off" setting will cascade to subclassed templates, but as of the version I have, this doesn't work. After some grepping, I came to a temporary solution. It turns out the constructor to the Context class has an undocumented new boolean parameter called, appropriately enough, autoescape. Its default value is True. I briefly considered adding "autoescape=False" to every call to the Context constructor, but quickly abandoned that idea. The solution I came up with was to actually edit the Django source code, in trunk/django/template/context.py. I modified the constructor so that the default value of autoescape is now False. On line 12:
class Context(object):
    "A stack container for variable context"
    def __init__(self, dict_=None, autoescape=False):
Hopefully, Django will provide a more permanent solution in the future. Ideally, it would be a setting in the "settings.py" file. For now, this small change allows me to continue developing with this useful set of tools.

Important note (Added Feb 26, 2008)

This page is getting a lot of hits, so I want to make clear that I do not recommend making the above change to the Django source permanently. This should be viewed as a TEMPORARY fix only, until you have time to migrate all your templates and code to deal with autoescaping correctly, that is, to keep it on except where you really need it to be off.