May 10, 2005

demangling 'property' values

I'm learning more about how properties work in Python. One thing I'm learning is that a property objects are only evaluated in the context of the parent object they're attached to.

After my last property trick, I now needed a way to manage groups of color tints. After thinking about it for a while, I ended up with:

    gradientLeft = tintedColor(0.4)
    gradientRight = tintedColor(0.2)
    outlineColor = tintedColor(0.5)
    textColor = tintedColor(0.67, 0.6)
    defaultColors = (gradientLeft, gradientRight, outlineColor, textColor)

I thought, "I'm brilliant! I'm extending the dynamic nature of 'property' to defaultColors"

But unfortunately, I ended up with something ugly instead.

What I got back was:
>>> col.defaultColors
(<property object at 0x009D9530>, <property object at 0x01351530>, 
<property object at 0x013B5378>, <property object at 0x013B53A0>)

That's not helpful at all! If I tried to access col.defaultColors[0], I got a property object rather than an rgb tuple.

I think the problem is that when I said col.defaultColors[0], the property object didn't know it was being accessed as a property of an object, so it didn't unwrap itself. It looked like I was going to have to do that unwrapping myself.

Sure enough, if I look at the property object, I can see what to do:
>>> dir(col.selectedColors[0])
['__class__', '__delattr__', '__delete__', '__doc__', '__get__', 
'__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__
', '__set__', '__setattr__', '__str__', 'fdel', 'fget', 'fset']
Ah! So all I have to do is call fget():
>>> col.selectedColors[0].fget()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: getSaturatedColor() takes exactly 1 argument (0 given)
Of course, because it needs a "self" argument. I have one ('col') but its not being used in the context of the call to fget. Lets try passing it in:
>>> col.selectedColors[0].fget(col)
(216.75, 255.0, 255.0)

Ah! So now I need a way to unmangle each element in the list, at the time the list is accessed.. what could I possibly use build the list then? I know, property()!

and thus we have tupleProperty. like tintedColor, we need to essentially curry some state to the property call, so we need to wrap it with a function.
    def tupleProperty(*args):
        def demangledTupleGetter(self):
            return [val.fget(self) for val in args]
        return property(demangledTupleGetter)
now, we can redefine defaultColors as appropriate:
    defaultColors = tupleProperty(gradientLeft, gradientRight, outlineColor, textColor)
what's particularly neat is that we can change the hue and the right properties will be called:
>>> col.defaultColors
[(153.0, 255.0, 255.0), (204.0, 255.0, 255.0), (127.5, 255.0, 255.0), 
(50.489999999999995, 153.0, 153.0)]
>>> col.eventHue = 0.0
>>> col.defaultColors
[(255.0, 153.0, 153.0), (255.0, 204.0, 204.0), (255.0, 127.5, 127.5), 
(153.0, 50.489999999999995, 50.489999999999995)]

I think the only bummer here is that I had to dive into the internals of python in order to make use of fget() and untangle this duple/property dependency.

Posted by alecf at 11:36 AM | Comments (0) | TrackBack

May 01, 2005

Looking at Tiger

Wow, I've just started reading Ars Technica's first look at Tiger. Needless to say I'm impressed. It sounds like they've done quite a bit under the hood this time around, making for a really interesting platform. Between that and trying to make ugly apps pretty with wxWindows, I'm getting jealous of people writing mac-only apps.

A few of my favorite things in Tiger that I've read about:
  • Incrementally better support for 64-bit addressing. Not tremendously interesting in itself, but its helping Mac keep pace with ia64 without completely revamping the whole OS like you have to do when running linux-ia64.
  • launchd - very cool replacement for the umteen different ways unix-like OS's use for launching processes not directly invoked by the user. It replaces inetd, cron, initd, and more. Good riddens.
  • Awesome filesystem support - ACLs, strong lightweight metadata, etc. I think WinFS is such a cool idea and I hope OSX and Linux can eventually follow suit.

And that's just the beginning. I need to finish the article. Next stop, I might have to get myself a personal Mac.

Posted by alecf at 09:03 PM | Comments (0) | TrackBack