August 25, 2014

Ferguson and keeping high-IQ folks out of the U.S. police force

I was really amazed at the sheer stupidity of the hate-filled rantings of one of the Ferguson cops (something like 35 years on the force). He seemed extremely confident of his completely illogical opinions.

But maybe this is a clue why that can happen: If you're very intelligent, you literally are not allowed to be a cop! At least in certain locales in the U.S.:


Jordan, a 49-year-old college graduate, took the exam in 1996 and scored 33 points, the equivalent of an IQ of 125. But New London police interviewed only candidates who scored 20 to 27, on the theory that those who scored too high could get bored with police work and leave soon after undergoing costly training.

The average score nationally for police officers is 21 to 22, the equivalent of an IQ of 104, or just a little above average.

Jordan alleged his rejection from the police force was discrimination. He sued the city, saying his civil rights were violated because he was denied equal protection under the law.

But the U.S. District Court found that New London had 'shown a rational basis for the policy.' In a ruling dated Aug. 23, the 2nd Circuit agreed. The court said the policy might be unwise but was a rational way to reduce job turnover.

 

"Might be unwise"... I'd say so! 

Save a little money by reducing job turnover by mandating a police force of not particularly high intelligence. I.e., at best, not particularly good skills for looking at evidence and deciding what it means. And, more subtlety, but perhaps even more importantly, not particularly good self-critical abilities -- the abilities necessary to consider whether one's own upbringing-based assumptions, often including assumptions about the inferiority of other groups, might be problematic in some way.

I'm not sure how tightly police force IQ's cluster around 104, but it may be that almost half of police, those whose job description includes looking at the often-confusing data around them and deciding whether lethal force is warranted, have a below-average ability to do so (at least as that ability is determined I.Q., which I would guess is a very important component). I would think that positions entailing that kind of critically high responsibility should require job candidates with unusually high relevant abilities.

Put those dangers together, and suddenly something like 6 bullets pumped into an unarmed kid seems a bit more understandable.

I've always wondered how the U.K. strategy of having largely gunless police could make sense, considering the fact that those police have to stop criminals who do have guns. Now it doesn't seem as mysterious -- at least if the U.K. police force has a similar average IQ to the U.S.. I'm in no position to claim it's the right choice for the U.K. as a strategy, but at least it makes a little more sense.



August 25, 2014 in Current Affairs | Permalink | Comments (0)

October 27, 2013

There are 10 kinds of people in the world...

An observation found on a t-shirt my son owns, and which I also noticed today on Hacker News:

There are 10 people in this world, those who understand binary and those who don't.

 The first reply on Hacker News:

There are 10 kinds of people in this world: Those who understand ternary, those who don't, and those who mistake it for the binary system.

October 27, 2013 | Permalink | Comments (0)

October 11, 2013

Unit Testing with Durandal

Durandal provides the Durandal Test Framework for unit testing. This test framework uses PhantomJS and Jasmine.

As shipped with Durandal, it's focused on testing Durandal's own internal components. But it can easily be adapted for your own unit testing needs.

You can obtain the test framework by downloading the entire Durandal project with

git clone https://github.com/BlueSpire/Durandal.git

(assuming, of course, you have git installed).

Note that if you're not on Windows, you'll also need to install PhantomJS on your system, since the PhantomJS that comes with the Test Framework is a .exe.

In your own work, you're probably not going to want to use the entire Durandal project -- you may start with a starter kit such as the HTML Starter Kit, or even with your own custom setup. The first challenge is that the Starter Kits don't include the Test Framework. Beyond that, since the Test Framework is configured out-of-the-box for Durandal's internal testing needs, its hardcoded paths don't work for the directory hierarchies you'll have as a developer.

But configuring the Test Framework for your own needs is very easy. Edit spec.html in the test directory. In that file, you'll see that require is configured with some paths:

    paths: {
        'specs': '../test/specs/',
        'text': '../lib/require/text',
        'durandal': 'durandal/js',
        'plugins' : 'plugins/js',
        'transitions' : 'transitions/js',
        'knockout': '../lib/knockout/knockout-2.3.0',
        'jquery': '../lib/jquery/jquery-1.9.1'
    }

For the HTML Starter Kit, with the test directory copied into the top-level directory at the same level as lib, css, and app, you only have to change three of them:

        'durandal': '../lib/durandal/js',
        'plugins' : '../lib/durandal/js/plugins',
        'transitions' : '/lib/durandal/js/transitions',

In general, you just need to find the durandal, plugins, and transitions directories and set the paths appropriately.

It's also helpful to add a path to the app directory where your code will live:

        'app': '../app',

You can test your paths by removing the existing test modules from test/specs (which will no longer work, since they are for Durandal's internal testing) and replacing them with a new, dummy test module such as:

define(['viewmodels/flickr'], function (flickr) {
    describe('', function(){
        it('returns true', function () {
            expect(true).toBe(true);
        });
    });
});

This sets up testing for the flickr module that ships with the HTML Starter Kit. If you're using some other setup, you'll need a different test. But this shows how it's done. It doesn't test every path, but since the flickr module uses the durandal and plugin paths, it tells you whether you're on the right track.

To run the test:

$ phantomjs spec.js

You'll know that you don't have the paths set correctly if you get a error like the fullowing, which leads to a hang of PhantomJS:

Running spec files: specs/mytest.spec
Error: Script error
http://requirejs.org/docs/errors.html#scripterror

  file:///Users/garyrob/Source/Durandal%20Projects/HTML%20StarterKit%20(Durandal%202.0)%20Exp%202/lib/require/require.js:32
  file:///Users/garyrob/Source/Durandal%20Projects/HTML%20StarterKit%20(Durandal%202.0)%20Exp%202/lib/require/require.js:12 in C
  file:///Users/garyrob/Source/Durandal%20Projects/HTML%20StarterKit%20(Durandal%202.0)%20Exp%202/lib/require/require.js:29

If all is well, you should see something like:

    Running spec files: specs/mytest.spec
    Starting...

    Finished
    -----------------
    1 spec, 0 failures in 0.002s.

And you'll be ready to unit test your new Durandal project!

October 11, 2013 in Durandal | Permalink | Comments (0)

October 07, 2013

Javascript and SPA's, as seen by a long-time Python developer

I love Python and have posted a number of Python tips on this blog. And I've been involved in the creation of sizable web sites using Django.

But I've come to feel that for many types of web sites, doing all the rendering on the server and shipping the rendered page to the browser is probably not be the best way to go. Certainly, I'm not the first to come to that conclusion. Google Docs is a phenomenal example of what can be done in a "single page app" (SPA) rendered in the browser. There are many others.

In the course of investigating the various technologies for creating SPA's, one thing I've come to appreciate about that strategy is that you may not need much of a server at all. If you use something like Firebase for your database, you may need nothing more than a means of serving static html and JavaScript files on your server. And then you can use a CDN like CloudFlare to keep you online even if that server is temporarily down. All these factors together can eliminate an enormous amount of overhead in server administration.

Eliminating such overhead seems like it could be very helpful for my goal of creating my next project entirely by myself.

Unfortunately, JavaScript is (IMO) not nearly as nice a language as Python. But if used according to certain patterns, such as described in the famous JavaScript: The Good Parts, a lot of its deficiencies are mitigated, and then it's really not so bad. And most modern JavaScript libraries use the language in that way, so the ecosystem as a whole supports you in that.

Javascript even has Python-like constructions such as list comprehensions. And there are other languages that compile to JavaScript and can be fairly easily integrated into JavaScript projects, such as CoffeeScript -- which itself is Python-like in a number of ways, including semantic indentation

You can put together tools such as Firebase, Knockout and KnockoutFire to cause changes in your database to automatically and near-instantaneously show up on-screen in your SPA with trivially little code through data-binding. Of course, there are ways of doing that with a framework like Django as well, but data-binding is integral to the way some SPA frameworks operate.

Lately I've been experimenting with Durandal as my SPA framework. It incorporates Knockout, and I'm using KnockoutFire to connect it to a Firebase database. Using a framework like Durandal provides organization for your code, and provides facilities like routing.

So far, I'm very impressed. The main drawback (other than already-noted inherent weaknesses in Javascript itself) is that the documentation and ecosystems of long-existing, high-profile projects like Django are much more evolved. But those things will get better in time, and I'm looking forward to continuing my explorations with Durandal and Firebase.

October 7, 2013 in Python | Permalink | Comments (0)

April 27, 2012

If you get stuck trying to Empty Trash in OS X

A few times, I've had a problem where the progress bar would stop progressing when I tried to empty the OS X Trash. Even going into the Terminal and trying to delete the files via  sudo rm  causes that command to just sit there, making no progress. Rebooting the computer doesn't help. (And, just to be even more fun, the computer may not even allow itself to be rebooted without restarting the Finder first.)

Every time this has happened that I can recall, the problem has been with the "ownership" of some files in the Trash.

Luckily, there's a very easy solution. Go to the Terminal, and enter:

sudo chown -R xxxxx ~/.Trash/*

(replacing xxxxx with your usual OS X "short" login name.) You'll have to enter an admin password.

After that, you should be able to Empty Trash from the Finder as usual with no problems.

April 27, 2012 | Permalink | Comments (0)

April 09, 2012

Thanks

Please allow me to take a brief moment here to give me deepest, most heartfelt thanks to Maine-based periodontist Dr. Laura Reidy and her husband, dentist Dr. Jonathan Tozer, and one of their staff – whose name I am very sorry to say I have forgotten, but which I will find out and post here – who detected the cancer early enough to probably save my life. (This staff member noted the first signs of cancer in a regular cleaning session; she alerted Dr. Tozer, who alerted Dr. Reidy.)

In particular, Dr. Reidy did something -- twice -- that I will be eternally grateful for. At first, it looked like it might be cancer, so she sent me to a cancer surgeon, who took biopsies and came to the conclusion that it wasn't.

Although Dr. Reidy is not a cancer surgeon, she looked at my mouth and would not let the matter rest with the surgeon's judgement. She took another biopsy herself, sent it off to be examined, and it came back positive. Her pro-active approach, skill at collecting usable biopsy, and courage to question the surgeon's conclusion, may well have saved my life, because the cancer was caught before there was lymph node involvement. As noted in my previous post, the difference is a 68% vs. 17% five-year survival rate for the type of cancer I had.

I then went to another cancer surgeon, and had surgery which removed some of my palate and upper teeth.

A year after my first surgery, my surgeon thought a spot on the edge of the surgical area looked a little suspicious, and did a "spot biopsy." It came back negative and he didn't pursue it. But when I saw Dr. Reidy two months later, she saw the same suspicious area and was again unwilling to assume that the surgeon's biopsy was correct. Her instincts told her it was still worrisome. She took another biopsy, and it came back positive. So, she may have saved my life not once, but twice, after she and her husband (and that assistant) identified it as possibly being cancer in the first place.

I went to yet another surgeon, the excellent Dr. Charles Norris in Boston, who did more surgery in the same area. And this time, the cancer does indeed appear to be gone -- at least there's been no sign of it in more than five years, and the prognosis is therefore good.

So, my deepest, most sincere thanks to all those who helped me. There is no way I can express my gratitude enough.

 

April 9, 2012 | Permalink | Comments (0)

Update

I have resigned from Emergent Discovery, LLC. I'm the main founder of the company (although I wasn't the CEO), so it is a sad thing. But I finally came to feel I'd be happier doing something else, and that my family would be happier too if I didn't come home as frustrated as I'd been.

Actually, I will go so far as to say that Steve Jobs' death had something to do with it. In his Stanford commencement address he said:

When I was 17, I read a quote that went something like: "If you live each day as if it was your last, someday you'll most certainly be right." It made an impression on me, and since then, for the past 33 years, I have looked in the mirror every morning and asked myself: "If today were the last day of my life, would I want to do what I am about to do today?" And whenever the answer has been "No" for too many days in a row, I know I need to change something.

After Jobs died, I watched that address, which I hadn't seen before. And I noticed that he'd been moved by something he'd happened to see, and that it had, perhaps, been an influence toward changing his life. And I thought, why shouldn't the same happen with me? The fact is that when I looked in the mirror and asked myself the same question Jobs asked himself, the answer would have been "No." For too many days in a row.

The fact is, life is very short. I probably have a more visceral sense of that fact than some people do because I've had cancer. I never talked about it on this blog, but my voice here, moving forward, will be more personal than it was in my Emergent period. This cancer, oral squamous carcinoma, led me to undergo two major surgeries. The upper part of my mouth is largely replaced by a prosthesis (I do have five upper teeth left, which the prosthesis attaches to).

One article says:

For carcinoma of the palate and tonsillar area, 5-yr survival is 68% if patients are treated before lymph node involvement but only 17% after involvement.

The cancer was caught earlier enough that I had no lymph node involvement. But I was highly conscious of the fact that I might die. A year after the first surgery, which removed a good part of my palate, the cancer came back. That, obviously, was quite scary. I had a second surgery, continuing to work hard for Emergent all that time except for basic surgical recovery periods.

Since then there has been no sign of cancer for more than five years.

But, I don't take life for granted. Anything can happen; cancer can return, and there are certainly many other ways of exiting the stage! Life is simply too short and precious to waste a minute of it.

I was therefore primed to hear the combined message of Steve Jobs' speech and, not many years later, his death. And it became one of the catalysts (there were others) leading to a long period of trying to work out what could change so that I would feel differently about working at Emergent. In the end, for a number of reasons, the best answer seemed to be: I should resign.

I don't think it's the time to go into a detailed post-mortem. I wish Emergent well, and I'm moving on. At this point, I'm much more interested in the future.

I'll probably be posting more to this blog, and I'll certainly use it to talk about my next project. I haven't decided yet what that will be. I'm researching and considering various, very diverse options now.

But I do know that I won't have a cofounder. In fact, I'm going to try to get a web services or mobile app off the ground without even an employee.

The technology is vastly better than it used to be. Cloud services like Heroku eliminate many of the technical and hardware barriers.

Virality can lessen the need for traditional marketing expertise, though that can will occur if and only if you have the right idea at exactly the right time, and build a good-enough, attractive-enough embodiment of it. Of course, you can create and test a series of minimum viable products representing different ideas strategies, which gives you a few shots at coming up with the idea. But it's still a Very Hard Thing To Do. On the other hand, if you can achieve it, you can build a business with precious little marketing expenditure.

That's what I'm going to try to do. Build the technology myself, leveraging "the cloud," and try to spark virality. Of course, I may fail, but I think I'll succeed. This view of the world may be wrong, but no one will accuse me of not acting in accordance with it.

Once the product is off the ground, and has achieved a non-trivial degree of critical mass, I'll consider looking for investment and people who can come aboard and help scale it.

I do have some reason to think this is not impossible. For one thing, I created one of the first viral computer services that ever existed. This was a voice-mail-based dating service called 212-ROMANCE, which I started in the early 1980's. As far as I know, it was the first such service. It was enough of the right-idea-at-the-right time, that after I initially ran one small ad once in the Village Voice, usage grew continually until all phone lines were busy continuously. It was spread entirely by word-of-mouth. Eventually, I could go to a party and people I met there would already know about it.

As an aside, because it took a long time to listen to personals ads, I needed a way for the system to play the ads that were most appropriate for each caller first. I designed and implemented a solution that would now be referred to as "collaborative filtering". I'm not aware of that concept being written about or implemented before that (if you know otherwise, please let me know).

So anyway… this post has covered a lot of ground, though none of it particularly in-depth. I wanted to bring this blog up-to-date and prepare the ground for more blogging in the future, and hopefully I've succeeded in that.

 

 

April 9, 2012 | Permalink | Comments (3)

February 02, 2012

(Not) calculating the product of a Python list of for comparison purposes

I came across a stackoverflow question about multiplying the numbers in a Python list. Suggestions there included:

def product(list):
    p
=1
   
for i in list:
        p
*= i
   
return p

and

from operator import mul
reduce
(mul, list)

Adding my own $.02, you can also do:

import math
math
.exp(sum(map(math.log, list)))

which gets the same numerical results (at least to as way more decimal places than you're ever likely to care about, the difference being due to computational floating point errors). It's probably not as readable as the reduce-based solution, though if you're a mathematician who isn't familiar with reduce(), the opposite would be true!

(The underlying principle is that a * b * c * … * z == e ^ (ln(a) + ln(b) + ln( c) + … + ln(z)).)

I wouldn't necessarily advise using the log-based solution under normal circumstances. But if you're ever in a situation where you risk overflow or overflow, such as in

>>> reduce(mul, [10.] * 309)
inf

and your purpose is to compare the products of different sequences rather than to know specifically what the products are, then, you can accomplish your purposes without actually computing the entire product. Rather, you can compare the sums of the logs of the terms, without bothering to compute the product by taking the exponential. Whichever list has a larger sum-of-logs also has the larger product. So, following up on our previous example,

>>> sum(map(math.log, [10.] * 309))
711.49879373515785

is the way to go because it's virtually impossible to have a real-world problem in which you would overflow or underflow with this approach. (The larger the result of that calculation is, the larger the product would be if you could calculate it.)

Accordingly, if you wanted to compare 10. ^ 309 and 11. ^ 309, you could do

>>> sum(map(math.log, [10.] * 309)) > sum(map(math.log, [11.] * 309))
False

[Originally posted as "Calculating the product of a Python list. Updated for clarity and completeness.]

 

 

February 2, 2012 in Python | Permalink | Comments (0)

June 01, 2011

Selenium's WebDriver & Python: Dealing with script timeouts

Selenium's WebDriver is a great way to interact with web sites in an automated way. It's primarily for testing, though I've also had occasion to use it for other purposes (with the permission of the relevant site owners).

In order to interact with sites that use a lot of Javascript, it's helpful to use Selenium's Firefox driver. It works great, but I did have one problem, where scripts were timing out. You can modify Firefox's timeouts via changing preferences, but Selenium's Firefox driver uses its own profile, so it ignores Firefox's usual means for changing preferences.

I searched the web for solutions and found various suggestions that didn't work. Perhaps many of them worked with pre-WebDriver versions of Selenium, I don't know.

In any case, the following worked for me to change the timeouts to 10 minutes:

from selenium import webdriver

profile = webdriver.firefox \

.firefox_profile.FirefoxProfile()

set_pref = profile.set_preference

set_pref('dom.max_script_run_time', 600)

set_pref('dom.max_chrome_script_run_time', 600)

driver = webdriver.Firefox(fx_profile=profile)

Note that the dom.max_chrome_script_run_time preference has nothing to do with Google Chrome, it's related to Firefox's internal Chrome URL's. In fact, for my purposes, I only needed to change dom.max_chrome_script_run_time.

Note: if you're not familiar with WebDriver, do help(webdriver.Firefox) for a description of the methods you have available for interacting with sites. Hint: the oddest thing is that to fill in a text field, you get an object representing the element with the text field, and then call myElement.send_keys("the text").

Update: Docs on the Python bindings may be found here.

 

June 1, 2011 in Python | Permalink | Comments (3)

February 03, 2011

Profiles In Courage

 

I've been paying particular attention to one Egyptian who's been tweeting about events, whose Twitter ID is Sandmonkey. I don't know about you, but when I start following somebody via blogs or twitter and they are expressing what matters to them, I feel a bit like I know them. I start to care about them. Here are his most recent tweets (skipping the ones I can't read because they're in Arabic, and the ones that only link to another page):

Sandmonkey 
Anti-Mubarak protesters are descending on downton in the thousands. They are not giving up Tahrir. #JAN25
16 hours ago Favorite Retweet Reply

Sandmonkey 
I hear reports of Army evacuating the Square from Protesters. Is this true? #jan25
5 hours ago Favorite Retweet Reply

Sandmonkey 
Either way, I am heading there with medical supplies. They better not block my entrance. #jan25
5 hours ago Favorite Retweet Reply

Then somebody telling him how to get into Tahrir:

ahmada2 
@Sandmonkey it's open. Kasr el Nile or talaat harb.
5 hours ago Favorite Retweet Reply

Then…

SorayaBahgat 
Reports about my dear friend @Sandmonkey being arrested in#Tahrir. So worried can anyone give me more info? @bencnn#Egypt
1 hour ago Favorite Retweet Reply

and a number of other tweets from different people reporting the same thing, including:
lisang Lisa Goldman
.@sandmonkey was arrested today & his blog has been suspended. Read his very important final post about #jan25 here: http://bit.ly/hqIJ2b
That post ends:
"This is a losing battle and they have all the weapons, but we will continue fighting until we can’t. I am heading to Tahrir right now with supplies for the hundreds injured, knowing that today the attacks will intensify, because they can’t allow us to stay there come Friday, which is supposed to be the game changer. We are bringing everybody out, and we will refuse to be anything else than peaceful. If you are in Egypt, I am calling on all of you to head down to Tahrir today and Friday. It is imperative to show them that the battle for the soul of Egypt isn’t over and done with. I am calling you to bring your friends, to bring medical supplies, to go and see what Mubarak’s gurantees look like in real life. Egypt needs you. Be Heroes."
Update: He is out of jail now. "He was roughed up, but is fine." Sitting here in Bangor, Maine, enjoying the peaceful, beautiful snow, I'm in awe of this kind of courage.
Later update:

Sandmonkey Sandmonkey
I am ok. I got out. I was ambushed & beaten by the police, my phone confiscated , my car ripped apar& supplies taken #jan25
28 minutes ago Favorite Retweet Reply
Sandmonkey Sandmonkey
will tell the story later . Thank you all. I just need to rest now. #jan25
16 minutes ago Favorite Retweet Reply

 

Last update, Feb 11:

The courage of Sandmonkey and all the protestors has paid off. Unbelievable to have been privileged to watch this history unfold in real time. Here's the last tweet from Sandmonkey I'll post here:

 

Sandmonkey Sandmonkey

 

To everyone who rediculed us, opposed us, wanted us to compromise, i say: YOU ARE WELCOME :) TODAY WE ALL CELEBRATE!!! #JAN25

 


Now, let's hope that the ruling Supreme Council of the Armed Forces doesn't turn out to just enable a continuation of the same type of authoritarian regime...

 

 

 

 

 

 

February 3, 2011 in Current Affairs | Permalink | Comments (0)

October 02, 2010

How to tune a guitar

...if you're a luthier, that is.

I was wondering why a Yamaha classical guitar I purchased a few years ago always seems out of tune, and started a discussion about it in a guitar forum, including measuring the pitch while each string is open and fingered on the 5th and 12th frets (bizarrely inconsistent results). They suggested I check out this fascinating article by Gregory Byers. It describes the lengths (pun not intended but allowed) a guitar-maker has to go to to create a situation where each string is somewhat in tune on each fret. My Yamaha was not made that carefully! Of course very few guitars are. Byers spends a month making a guitar,  and they cost $9,500.

October 2, 2010 | Permalink | Comments (0)

Get yer mental health here!

A friend of mine, Tom Sulcer, with whom I like to harmonize on tunes like the Beatle's "If I Fell," posted a fairly massive article called "Mentally Healthy Mind" in a Google knowl. It touches on everything from deliberative democracy to Maslow to Spinoza. Did I mention that it's massive? My own impression is that most of the important understandings in life are largely unconscious and hard to modify through conscious deliberation, whereas Tom appears to try and leverage a conscious understanding of just about everything related to living a life. We'll see who's right by noting which of us plays better guitar at age 95.

October 2, 2010 | Permalink | Comments (1)

July 20, 2010

A Dog's Consciousness

Here's a way to imagine what it would be like to be a dog.

Take a few moments to imagine yourself exactly as you are now, with the exception of not being able to focus your attention on anything that exists only in your head. You don't even have to imagine not having thoughts. You just can't focus on them.

July 20, 2010 | Permalink | Comments (3)

October 17, 2009

Non-blocking raw_input for Python

[Edited Aug. 30, 2010 to fix a typo in the function name and generally improve formatting]

I needed a way to allow a raw_input() call to time out. In case it's useful to anyone, I wrote this solution which works under Unix-like OS's.

import signal

class AlarmException(Exception):
    pass

def alarmHandler(signum, frame):
    raise AlarmException

def nonBlockingRawInput(prompt='', timeout=20):
    signal.signal(signal.SIGALRM, alarmHandler)
    signal.alarm(timeout)
    try:
        text = raw_input(prompt)
        signal.alarm(0)
        return text
    except AlarmException:
        print '\nPrompt timeout. Continuing...'
    signal.signal(signal.SIGALRM, signal.SIG_IGN)
    return ''

 

 

October 17, 2009 in Python, Web/Tech | Permalink | Comments (3)

October 12, 2009

Snow Leopard Guest User data loss bug

I've seen a number of mentions today of a bug that can cause a Snow Leopard user to lose all their data:

The problem appears to manifest itself on machines which had the Guest account option enabled under Leopard and were subsequently upgraded to Snow Leopard. Users booting their machines have reported that upon start-up, they have been logged into the Guest account. Upon switching to their regular account, the affected users have been finding all of their user data missing and unrecoverable except from a backup. [MacRumors.]

One user reports a way to recover the lost data. Since it's buried in a discussion thread, I'm reproducing it here (also fixing a typo pointed out by a reader of this blog):
The files were still in /Users,
recovery was not too difficult.
1) su in terminal
2) mv username username.old
3) create account username
4) mv username username.new
5) mv username.old username
6) chown -R username username

I don't know whether it's a general fix. If you run into the bug and decide to try this solution, feel free to post your experience in the comments section!

October 12, 2009 in Web/Tech | Permalink | Comments (2)

September 11, 2009

FlyFi.com upgrade

We've made a substantial upgrade to the look and feel of our Flyfi.com web site. The site does a lot, and this release has been geared toward making the functionality more readily apparent and easier to use.

September 11, 2009 in Music, Web/Tech | Permalink | Comments (0)

August 02, 2009

FlyFi Community Playlist

If you're a Facebook user, you might want to check out my company's FlyFi Community Playlist app which lets a Facebook community collaborate on a playlist... but it's more than a playlist because it also provides tracks related to the manually entered ones.

A fair number of the tracks are legally downladable free MP3's, from superb artists like Randy Newman (one of my personal top 5 artists), Ani DiFranco, Suzanne Vega, Dar Williams, and many others.

August 2, 2009 in Music, Web/Tech | Permalink | Comments (0)

July 29, 2009

Correction re singletons

The source code link presented at the main post for my singleton mixin classes was bad until now. It pointed to an earlier version that didn't have thread safety or various other improvements. Sorry.

July 29, 2009 in Web/Tech | Permalink | Comments (0)

July 28, 2009

Even more singleton improvements

singletonmixin now deals with cases where you want to be able to include args in calls to S.getInstance() even after the initial instantiation.

July 28, 2009 in Web/Tech | Permalink | Comments (0)

July 27, 2009

More singleton improvements

Based on internal work and feedback appearing in comments on this blog, I've updated the Python singleton class I posted way back in 2004. That earlier post remains the place to get the code and place any further comments.

It now handles keyword arguments, and is threadsafe for singleton creation.

July 27, 2009 in Web/Tech | Permalink | Comments (0)