After my first week it generated a list of “neighbors” that shared my
musical tastes. Now after another week it updated my listening charts
again, and deleted my neighbors list! I guess I confused it from
starting off with The Flaming Lips,
Ween, and Lauren Hoffman
topping my list, to MF DOOM,
Girl Talk, and
CunninLynguists the
next week.
I guess it might take a little time for Last.fm to figure out my musical
tastes.
Update: Either I was impatient, or Last.fm is reading my blog. I
have a new set of neighbors now. Girl Talk’s “Night Ripper” was
definitely the album to listen to last week. Girl Talk is the top
weekly artist for most of my neighbors, and it’s the top mover on the
Last.fm charts at 500%.
Of course IE doesn’t support this part of the spec, and it’s not
included in the IE 7 beta, so it’s unlikely it will be supported in the
near future. So, one option that makes IE behave similarly to the
disabled options is to replace them with <optgroup> tags.
The <optgroup>s cannot be selected and with a little CSS they look like
disabled options. However, the static solution suggested didn’t work for
me since I needed to be able to disable or enable options at runtime.
So, with a little JavaScript (and the help of
MochiKit’s DOM functions) the options can be
enabled or disabled dynamically:
The display of disabled options is updated in the “onfocus” method to
make sure that changes in the disabled state of the options is reflected
before the <select> is displayed again. Disabling options can be done
directly to any of the option elements such as:
1
select.options[0].disabled=true;
However, a little care needs taken to re-enable options, since the
<optgroup>s aren’t in the “options” attribute of the <select>. The
original option needs reenabled by accessing it through the “_option”
attribute added to the <optgroup> element:
123456789
// reenable all disabled options in standards-compliant browsersforEach(select.options,function(option){option.disabled=false;});// reenable all disabled options in IEforEach(select.getElementsByTagName("OPTGROUP"),function(optgroup){optgroup._option.disabled=false;});
To make sure that this IE hack only gets loaded in IE, put it in a .js
file and wrap it in an IE conditional comment:
I’ve fixed up a couple of things in
Evolution that have been
irritating me for a while using filters to pipe the messages through
external apps.
New message notification
I’ve wanted to have popup notifications when I get new messages, so I
wrote a little Python script that parses the message and displays a
summary using Galago:
Installation
Download Ka-Ping’s scrape.py
library to somewhere on your PYTHONPATH (usually
/usr/lib/python2.4/site-packages; change the version number if necessary)
Download
mail-notify.py
and make it executable (chmod a+x mail-notify.py)
Add your Evolution filter (use Browse to pick the file if it’s not on
your PATH):
Working spam filtering
Spam filtering in Evolution used to work, but in recent versions I have
not seen it catch a single spam. At first it seemed like this was due to
not having SpamAssassin installed. After installing that it starts the
spamd process and thinks for a little bit when I try to mark messages as
junk, but still nothing gets caught.
So, I gave up on the built-in filtering and set up an Evolution filter
using Bogofilter:
Unfortunately Evolution doesn’t provide a way to just specify a program
to run when you click the Junk and Not Junk buttons, so I’m using
Spam Trainer to train Bogofilter. You can drag
messages from Evolution into Spam Trainer to mark them as “spam” or “ham”.
Set your Spam Trainer preferences to use the Bogofilter program:
Subversion includes a contrib script svn_apply_autoprops.py that scans your
auto-props
settings and applies them to a working copy. These are normally applied
to files you add to the repository, but this script is useful if you
have added new properties, or other users have added files without
configuring the desired properties. However, since I use
SVK this script didn’t work for me. I looked
at the script to see if I could convert it to use SVK instead, but it
was relying on the .svn folders to try to determine what directories to scan
and I didn’t like the fact that they were parsing the config by hand with
regular expressions instead of using the extremely useful
ConfigParser
module.
I decided it would be quicker to rewrite the script than to fix up the
existing one, so here is the new and improved version:
svn_apply_autoprops.py
Key features include:
Faster
This version is about twice as fast as the old one on the several
repositories I’ve tested. The old version walked the directory
structure for each pattern to find matching files. This version uses
svn status -v to find all the versioned files once and simply scans this
list to find the matching files.
Simpler
Using the ConfigParser and simplifying the directory scanning made this
new version about 1/2 the code of the old one.
SVK support
There’s a variable that is defined at the top of the script to
determine which command is used: svn or svk. Both support the same
arguments needed by this script and are easily interchangeable.
Once you’ve upgraded you’ll probably want to check out some plugins:
WebAdmin
Everyone will probably want to install this. It adds a web interface
for those administrative tasks you used to use
trac-admin for, plus you can even use it to
install new plugins, or manage which components are enabled from
your existing plugins.
Bitten
Bitten is a “Continuous Integration” build server. It monitors your
code repository for updates and will automatically run build and
testing scripts to make sure you know when a build was broken. You
can run your builds on multiple target platforms and generate
historical graphs of unit test results and code coverage.
LDAP Plugin
I haven’t tried this one out yet, but it should be useful for
administrators that use LDAP to authenticate users, since it now
also allows you to manage permissions based on LDAP groups, or even
store Trac permission information directly in LDAP.
Account Manager
This is one that I wrote that allows users to register a new account. It
currently supports htpasswd or htdigest files, but it is extensible
for storing accounts in other formats.
Trac Hacks
Trac Hacks is a site that offers hosting for Trac extensions and
will be a good place to look for new plugins, since hopefully the
development interest will grow now that the new release has been
made final.
I’ve repackaged my account management module as a plugin and uploaded it
on TracHacks.
Installation instructions are included in the README file in the source.
It’s a pretty simple process: run setup.py to build the Egg and copy it
into your Trac environment.
The next step is to extend the webadmin interfaces to provide a frontend
to configure the account manager settings.
Well, PythonEggs
sounded like a neat idea, and now they’ve made it possible to turn
Trac’s pluggable framework into a real plugin system. Simply stick your
extensions into an Egg, create a “plugins” directory in your
environment, and drop-in the file.
Jonas is developing a webadmin module for Trac as a plugin, and I took
his example and have repackaged my account management module. Turning it
into a plugin was quite trivial, but there are a couple of other things
I’d like to clean up tomorrow before I release it.
The Trac documentation should be updated soon to explain how to make
plugins.
Well, after hacking around a bit I’ve gotten
Snurf backported to Python 2.2 so that it
will run on my host.
Snurf writes out the blog to static HTML and RSS pages, which is kind of
nice. I’ll have to check on turning on the comment capability, though
I’ll need to decide how I want to do the templates for that.
Update: I’ve imported all my old posts from the previous PyBloxsom
blog. Here’s the little Python script I wrote to convert them:
pybloxsom2snurf
Who needs Python marketing when Ruby On Rails runs their development
site on a Python-based web application?
For those not familiar with Trac
it’s a combination of wiki and bug-tracking for software development
projects. I use it at work and help out as a
developer on it in
my spare time. And of course it’s all written in Python.
I’m trying to convince the other developers that we should include the
“Python Powered” logo as an easter egg in the next release. There’s
nothing quite like having your competitor do your advertizing for you.