Posted by Kevin D Smith @ 2:59 am on January 27th 2010

Seeing Stars in Python’s Function Definitions

I had a problem today that required the used of a couple of mandatory arguments and a bunch of keyword arguments that got converted to a piece of XML. The easy solution would have been simply to specify each mandatory argument and just use **kwargs to pick up the keyword arguments as shown below.

def foo(x, y, **kwargs):
   ...

Then in the body of the function, I could sort through the values in the kwargs dictionary to get the values. The problem is that while this would work, it puts all work of checking the keys of the kwargs dictionary on my shoulders rather than Python’s shoulders where it belongs. It also means that I would have to check for any missing keys and put default values into those slots (another thing that Python’s keyword specifiers allow me to do in the function definition). This is just unacceptable. I need Python to do it’s job, while still maintaining the ease of use of **kwargs. The other problem is that I now have kwargs with my keyword values, and x and y in local variables. It was this last thought that gave me an idea for a simple solution.

If you put all of your arguments into the function definition as either mandatory or keyword arguments, they all end up being local variables inside the function. Why does that matter? It means that you can use Python’s locals() function to return a dictionary containing all of those values! This is exactly what I needed. It allows you to let Python verify the spelling of each mandatory and keyword argument name, plus it allows you to specify default values for keyword parameters, and it puts all of the arguments into one nice data structure (i.e., dictionary). Plus, it’s very easy to do.

>> def foo(x, y, a=1, b=2, c=3, d=4):
       print locals()
>> foo('hi', 'bye', c=10)
{'a': 1, 'c': 10, 'b': 2, 'd': 4, 'y': 'bye', 'x': 'hi'}

Now the arguments can all be processed easily. However, there is one thing to watch out for in method definitions.

>> class Test:
>>     def foo(self, x, y, a=1, b=2, c=3, d=4):
>>         print locals()
>> Test().foo('hi', 'bye', c=10)
{'a': 1, 'c': 10, 'b': 2, 'd': 4, 'self': <__main__.Test instance at 0x100493b90>, 'y': 'bye', 'x': 'hi'}

Notice that since self is specified in the method definition, it also shows up in the locals() dictionary. You can use Python’s del to delete that extra key (using a copy of locals(), of course).

args = locals().copy()
del args['self']

Now we have a way of letting Python do its work to validate arguments, and we can easily process the arguments as a single chunk of data.

Posted by Kevin D Smith @ 8:51 pm on September 16th 2009

Installing ReportLab on Snow Leopard

I recently install Apple’s latest version of OS X Snow Leopard. So far I have to say I’m not terribly impressed. About the only enhancement that makes any difference to me is the Exchange support, and most people don’t need that. Anyway, I’ve had a few problems in other areas with Snow Leopard and installing ReportLab is one of them.

I did some digging around on the internet and found a lot of partial solutions, but nothing that completely worked for me. What finally did the trick was the following.

cd /Developer/SDKs
sudo mv MacOSX10.4u.sdk MacOSX10.4u.sdk.bak
sudo ln -s MacOSX10.5.sdk MacOSX10.4u.sdk
sudo CC=/usr/bin/gcc-4.0 ARCHFLAGS='-arch x86' python setup.py install

Not pretty, but it gets the job done.

Posted by Kevin D Smith @ 2:06 am on March 11th 2009

Toolbar Effects with the New MooTools More 1.2.1

The first release candidate of the MooTools More 1.2.1 package includes a ton of new features. Oddly enough, I wrote several packages almost identical to some of these about a year ago. It’s nice to see that I can now just use the pre-packaged versions.

One thing feature that I like to see in web applications is some sort of alert or toolbar at the bottom of the window that stays in place. In can pop in and out depending on whether it’s needed. With the new MooTools More package, it is easier than ever. Below is an example where we have a footer that goes across the entire width of the page. There is a button (called showhide) that causes the footer to pop in and out.

Here is the relevant HTML:

<style type="text/css">
<!--
body {
    font: 20px/1.5em 'Lucida Grande', sans-serif;
    margin: 0;
    padding: 0;
}
#content {
    margin: 15px 20% 15px 20%;
}
#footer {
    width: 100%;
    height: 75px;
    border-top: 2px solid #008000;
    background-color: #80ff80;
    padding: 8px;
}
#showhide {
    width: 100px;
    border: 1px solid red;
    background-color: #ff8080;
    padding: 7px;
    cursor: pointer;
}
-->
</style>
<body>
<div id="showhide">Toggle Footer</div>
<div id="content">
...
</div>
<div id="footer">My Footer</div>
</body>

The Javascript is shown here:

document.addEvent('domready', function() {
    var footer = $('footer');

    // Put the footer at the bottom of the window and pin it there
    window.addEvent('resize', function() {
        footer.unpin();
        footer.position({'ignoreMargins':true,
                         'position':'topLeft',
                         'offset':{'x':0, 'y':window.getSize().y}});
        footer.pin();
    });
    window.fireEvent('resize');

    // Make sure the content of the page doesn't get covered by the footer
    document.body.set('styles', {'margin-bottom':footer.getSize().y});

    // Make the show/hide button toggle the display of the footer.
    var showhide = $('showhide');
    showhide.pin();
    showhide.addEvent('click', function() {
        $('footer').slide('toggle')
    });
});

That’s all there is to it! The footer bar can be toggle by clicking on the showhide button and even when you scroll the footer stays attached to the bottom of the window.

Posted by Kevin D Smith @ 2:15 am on December 4th 2008

Using MooTools for Button Effects

The last few articles here have dealt with using CSS to create custom buttons with hover and click effects. While in a perfect world, the CSS versions would be enough, but in a world with MSIE, they fall a little short. Some versions of MSIE only allow active and hover effects on <a> tags, but what if you want to create a custom button using some other type of tag? For that case, you’ll have to resort to using Javascript.

There are many different Javascript libraries to make cross-browser differences fade away, but I have been leaning towards using MooTools. So my example here will be shown using MooTools, but I would imagine most of the other Javascript libraries would work as well.

The first thing we need to do is change our CSS code to use class names rather than the :active and :hover pseudo-classes. The new CSS code is shown below with the old selectors commented out for reference.

/* Old Selectors: #nav a:hover, #nav a:hover span */
#nav .btn-hover, #nav .btn-hover span {
    color: #2A5E5E;
    background-position: left -22px;
}

/* Old Selector: #nav a:hover */
#nav .btn-hover {
    background-position: right -22px;
}

/* Old Selectors: #nav a:active, #nav a:active span */
#nav .btn-click, #nav .btn-click span {
    color: #74A074;
    background-position: left -44px;
}

/* Old Selector: #nav a:active */
#nav .btn-click {
    background-position: right -44px;
}

Just so you don’t have to go back and look, our original HTML code was as follows.

<div id="nav">
<a href="#"><span>OK</span></a>
<a href="#"><span>Cancel</span></a>
</div>

In order for these new selectors to work, we have to apply the btn-hover and btn-click classes at the appropriate times. The events we are going to use are mouseover/mouseout for the hover effects, and mousedown/mouseup for the click effects. MooTools makes it insanely easy to add events to multiple elements using the $$ function in combination with the addEvents method. The code to do this is shown below.

window.addEvent('domready', function() {
    $$('#nav > *').addEvents({
        'mouseover': function(e) { this.addClass('btn-hover') },
        'mouseout': function(e) { this.removeClass('btn-hover') },
        'mousedown': function(e) { this.addClass('btn-click') },
        'mouseup': function(e) { this.removeClass('btn-click') }
    })
})

You’ll, of course, have to include the MooTools Core and More scripts from the MooTools web site. As you can see from the code above, the btn-hover class is added and removed by the mouseover and mouseout events, respectively. And the btn-click class is added and removed by the mousedown and mouseup events, respectively. The $$ function is selecting all immediate children of the element with ID of “nav”. In this case, that would be the <a> elements. With all of this in place, all of the button effects should work in all browsers now even if you use elements other than <a>.

Posted by Kevin D Smith @ 3:17 am on December 3rd 2008

OnClick Effects with Buttons

The last article I posted here showed how to add hover effects to CSS-styled buttons. It is possible to use a similar technique to add onclick effects with CSS. This technique works well in Safari and Firefox, but not quite so reliably in Internet Explorer so you may want to combine this technique with the onclick support of Javascript libraries like MooTools.

The first thing to do is add another image to our button sprite. We’re going to add a green version of the button to display when the button is clicked. Here is our button sprite with all three variants.

To create the onclick effects, we are going to use the CSS :active pseudo class. The CSS code itself is almost identical to the CSS code used in the hover effects.

#dialog a:active, #dialog a:active span {
    color: #74A074;
    background-position: left -44px;
}
#dialog a:active {
    background-position: right -44px;
}

The only difference between this CSS code and the hover CSS code is that the :active pseudo class is now being using instead of :hover, and the background position has been shifted up by another 22px to display our third button image (we also changed the text color of the button to coordinate). Now when you click on the button, you’ll see the following effect.

As mentioned earlier, you have to be a bit more cautious with this trick because MSIE doesn’t work so well, but using Javascript and onclick events you can set the background position programatically to get the same result.

Posted by Kevin D Smith @ 1:36 am on December 3rd 2008

Hover Effects with Buttons

The last article I posted showed how to use a single button image to create variable width buttons with custom backgrounds. That’s all well and good, but what about hover effects? You can change the look of your buttons, including the background image very easily.

The first thing we need is an image that contains both the default and hover versions of the button. Put the default image on top and the hover image below it as shown here.

Now all we do is add new rules for the hover action. All the new rules have to do is change the background-position so that rather than getting the default button image, we reposition the background image so that we see the hover background image. To do this, we simply bump the background image up by the height of the button (22px in this case). We also added a text color change just for kicks. Here are the CSS additions for the hover effects.

#dialog a:hover, #dialog a:hover span {
    color: #2A5E5E;
    background-position: left -22px;
}
#dialog a:hover {
    background-position: right -22px;
}

With these rules in place, hovering over a button gives the following effect.

Posted by Kevin D Smith @ 11:21 pm on December 2nd 2008

Simple Variable-Width Buttons with Backgrounds in CSS

A lot of times when people create buttons on web pages, they want them to have nice gradients in the background and rounded corners and such. The trouble is that in order to create nice looking buttons like that, you either have to make the button contain the text itself, or you have to chop up the image into pieces and use the sliding door technique. The problem with putting the text in the image is that it is much more difficult to do translations. The sliding doors technique is annoying because you have to chop your images up. However, there is a third way which is much easier and will work in most cases.

The third technique is a lot like the sliding doors technique, but doesn’t require you to chop the image up. All that it requires is an image that looks like the button you want to create and is wider than any content that you may want to put into it. We’ll use the button shown below.

We are going to create a typical dialog style button bar with an OK button and a Cancel button. The HTML for this is shown below.

<div id="dialog">
<a href="/"><span>OK</span></a>
<a href="/"><span>Cancel</span></a>
</div>

Each button in this code consists of both an <a> tag and a <span> tag. The names of the tag aren’t important, but you do need to have two of them: one to render the left side of the button and the other to render the right side of the button. In our example, we are going to use the <span> tag to render the left side and the <a> tag to render the right side. Let’s start with the left side first.

The CSS code below will put our button image behind the <span> tag as well as set the height of the element to the same height as the background image and set the appropriate font size.

#dialog a span {
    background: transparent url('button.png') no-repeat scroll left 0;
    display: -moz-inline-box;
    display: inline-block;
    height: 22px;            /* Same as height of background image */
    font: 16px/22px "Lucida Grande", Arial;
}

We used the inline-block display type so that we could set the height of the button properly. Since Firefox 2 doesn’t support the inline-block type, we had to use -moz-inline-box as well. With these rules applied to our HTML, we get the following representation.

The text is crammed onto the left side, so add the following padding rule to the above CSS code to give us some room on the left side.

padding: 0 0 0 15px;

Our buttons should now look like the following.

We’re almost there, we just need to get the right hand side of the buttons rendered. Of course, that’s where the trick comes in. We are going to add 15px of margin to the right of each <span> tag (using margin: 0 15px 0 0). This will allow 15px of the <a> element to show through. We then use the same background image that we used for the <span> element except that we align it to the right side of the element. Here is the CSS rule for the <a> tag.

#dialog a {
    background: transparent url('button.png') no-repeat scroll right 0;
    display: -moz-inline-box;
    display: inline-block;
    height: 22px;
    font: 16px/22px "Lucida Grande", Arial;
}

We now have nice looking buttons using just a single image and CSS!

Since most of the rules for the <span> and <a> tag are the same, we can combine those rules and just override the differences in a second rule. We’ll also add a couple of attributes to set the color of the text and turn off any link underlining.

#dialog a, #dialog a span {
    background: transparent url('button.png') no-repeat scroll left 0;
    margin: 0 15px 0 0;       /* 15px == amount of background image to the right */
    padding: 0 0 0 15px;      /* 15px == amount of background image to the left */
    display: -moz-inline-box; /* Firefox 2 support for inline-block */
    display: inline-block;    /* Must be used so that height can be set */
    height: 22px;             /* Same as height of background image */
    font: 16px/22px "Lucida Grande", Arial; /* Appropriate font size / line height */
    color: black;
    text-decoration: none;
}
#dialog a {
    background-position: right 0;
    margin: 0;
    padding: 0;
}

Here is the final result.

Not only can you use this technique for buttons, but you can also use it to style tabs the same way. While this isn’t a perfect solution since it requires a fixed height font to be used in the button, it is a simpler way of handling styled buttons since you don’t have to worry about slicing and dicing your button backgrounds.

Posted by Kevin D Smith @ 9:58 am on May 14th 2008

Django and ModelForm

The current SVN version of Django has a new way of creating forms for adding and editing objects in a database. The most recent released version, 0.96, had two functions to create objects that generated forms for you: form_for_model and form_for_instance. The form_for_model function would take a Model class and generate an input form for it. The form_for_instance function would take a Model class instance and do the same, but would also fill in the values specified in the database. These were pretty handy, but it was inconvenient to have two functions that did basically the same thing. So the Django team added ModelForms.

ModelForms combine the features of the two previously mentioned functions into a single ModelForm class. Let’s say that we have a Student model in our Django application and we want to create a form for it in our view. We would create a subclass of ModelForm as follows.

from django.newforms import ModelForm

class StudentForm(ModelForm):
    class Meta:
        model = Student

If you were to create an instance of StudentForm in a view method and run the as_table method, you would get an HTML form that contained all of the fields in the model. A sample view method is shown below that creates a new user if there isn’t posted data, or saves the student information if there was posted data.

def studentEditor(request):
    # Save the newly created student using posted data
    if request.method == 'POST':
        form = StudentForm(request.POST)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect('/students/')

    # Create a new Student with no data
    else:
        form = StudentForm()

    return render_to_response('studentEditor.html', {'form':form})

This is great, and does basically the same thing as the old form_for_model function, but it still leaves the editing portion to be done. Before ModelForms came out, you had to use the form_for_instance function to convert an existing instance to a form instance, then render the HTML form to edit the data. Now it is much easier. You simply add an ‘instance’ keyword option to the ModelForm constructor that speficies the instance to read the initial data from. Below is the same view as above with a new argument that is the primary key of a student in the database. This primary key is used to get a student instance to pass to the StudentForm constructor.

def studentEditor(request, id=None):
    instance = None
    if id is not None:
        instance = Student.objects.get(id=id)

    # Save the created or edited student using posted data
    if request.method == 'POST':
        form = StudentForm(request.POST, instance=instance)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect('/students/')

    # Create/edit a Student with database values
    else:
        form = StudentForm(instance=instance)

    return render_to_response('studentEditor.html', {'form':form})

This is pretty nice, but there is still a redundancy in creating the StudentForm instance. You have to do it in two different places for the create and edit cases. However, with a couple of little Python tricks using ‘and’ and ‘or’, you can simplify the above code to this:

def studentEditor(request, id=None):
    form = StudentForm(request.POST or None,
                       instance=id and Student.objects.get(id=id))

    # Save new/edited student
    if request.method == 'POST' and form.is_valid():
        form.save()
        return HttpResponseRedirect('/students/')

    return render_to_response('studentEditor.html', {'form':form})

Now that’s an idiom that would make a mother proud.

Posted by Kevin D Smith @ 10:39 pm on April 3rd 2008

MooTools & Garbage Collection

I’ve been working on a MooTools class for the past couple of days that makes large data tables scrollable. When the page loads, it checks to see if any data tables are larger than the scrollable area of the window. If there are tables like this, it puts the table into a scrolling div and copies the header and footer areas above and below the scrolling div, respectively. It also has the options of making the rows alternate colors and making the table rows sort when the headers or footers are clicked. I had it working quite well, but there were some performance issues.

The table I was testing with had 429 rows of 16 columns. This is a total of 6864 cells. I was taking advantage of MooTools’ getElementBySelector in many places because I needed to find th and td cells within the tbody, thead, and tfoot elements separately. This created some problems when the page unloaded. On Firefox, it was taking over 7 seconds just to leave the page. This obviously was unacceptable.

I was having trouble figuring out what the exact problem was. I’m having done a lot of Javascript debugging, and have done even less performance profiling. Luckily, the Firebug plugin to Firefox was a huge help. In fact, I don’t know how I would have figured out the problem if I hadn’t had it. I turned on profiling then refreshed my page. Firebug told me that the ‘remove’ method of the MooTools Array object was taking up all of the time. I wasn’t using the remove method, so I figured there must be some sort of garbage collecting going on in MooTools. After posting to the MooTools forum, I got the answer. Apparently, whenever you use any of the MooTools that returns a DOM node, it extends those nodes with the special MooTools methods. This means that if you use $, $$, getElementsByClassName, or getElementsBySelector, every node that is returned is extended by MooTools and must be garbage collected.

In my table, I had thousands of cells that I was accessing to implement various features. Every one of those cells was being extended and had to be garbage collected. By the time my script was finished, I had over 7,000 objects to be garbage collected when the page unloaded (as seen in the Garbage.elements object under the DOM tab in Firebug).

While the getElementsBySelector method is very handy, it wasn’t going to work for me because of the extreme number of cells in my table. I ended up rewriting much of my code to use the standard getElementsByTagName method to get around the issue. This made the code quite a bit uglier, but I guess most optimizations do. The lesson today is to be careful when using methods that extend nodes in MooTools. While MooTools is really nice, there can be too much of a good thing. I’ve heard that MooTools 1.2 does memory management in a very different way, so hopefully the severity of this type of situation will be reduced in the future.

Posted by Kevin D Smith @ 7:38 am on March 25th 2008

Life with MooTools

It’s been a while now since I’ve started using the MooTools Javascript toolkit, and I haven’t regretted that decision once. MooTools still doesn’t have a following as big as Prototype or jQuery or maybe even Dojo, but it just seems to fit my code aesthetic the best. I love how non-invasive MooTools is when the HTML is concerned. Applying a function to elements based on selectors is fairly easy.

$$('.myelem').each(function(item) {
    myfunction(item);
});

This idiom is actually the way that you deal with arrays in general. Another highlight of MooTools is the Class object. This object lets you program classes in Javascript much like in other class-based languages like Java or Python. I couldn’t possibly do a better job of demonstrating classes than this tutorial on //clientside. When I originally started using MooTools, I didn’t think I was going to use the Class object much, but it has ended up being one of my favorite things.

Last but not least in the world of MooTools is the effects library. You can get a good feel for the quality of the MooTools effets simply by going to their web site. It’s hard to ignore the slick animation effects that MooTools gives you access to. The only trouble with effects is that it can be pretty easy to go overboard and start to make some really tacky web sites; however, in moderation, visual effects can really make your work stand out.

There are lots of other cool things about MooTools such as custom events and introspection of style attributes. If you use MooTools, I’d like to hear what your favorites idioms and features are.

Next Page »