Miscellaneous

Posts that don't belong anywhere else

Most of my personal projects are built on top of ASP.NET, Mono and Lighttpd. One of the benefits of keeping them all running on the same stack (as opposed to mixing Python, Mono and PHP together) is that I don't need to maintain different infrastructure bits to keep them all up and running. Two key pieces that keep it easy to dive back into the the side-project whenever I have some (spurious) free time are my NAnt scripts and my push scripts.

NAnt
I use my NAnt script for a bit more than just building my web projects, more often than not I use it to build, deploy and test everything related to the site. My projects are typically laid out like:

  • bin/ Built DLLs, not in Subversion
  • configs/ Web.config files per-development machine
  • libraries/ External libraries, such as Memcached.Client.dll, etc.
  • schemas/ Files containing the SQL for rebuilding my database
  • site/ Fully built web project, including Web.config and .aspx files
  • sources/ Actual code, .aspx.cs and web folder (htdocs/ containing styles, javascript, etc)

Executing "nant run" will build the entire project and construct the full version of the web application in the site/ and finally fire up xsp2 on localhost for testing. The following NAnt file is what I've been carrying from project to project.

  1. <?xml version="1.0"?>
  2. <project name="MyProject" default="library" basedir=".">
  3. <property name="debug" value="true" overwrite="false" />
  4. <property name="project.name" value="MyProject"/>

A while ago I jotted down about seven or so ideas of stuff that I thought would make good blog posts, somehow "markup parsers in Python" is next on the list, so I might as well spill the beans on how incredibly easy it is to process (X)HTML with Python and a little built in class called HTMLParser.

There have been a few occasions when I needed a quick (and dirty) way to perform transforms on some chunk of HTML or merely "search and replace" parts of it. While it might be cleaner to do something with XSLT or the likes, using them doesn't even begin to match the speed of development of an HTMLParser-based class in Python.

Getting Started
One major thing to keep in mind when working with HTMLParser, especially if you're newer to Python, is that it is what's referred to as an "old styled" object, meaning subclassing it is a bit different than "new styled" classes. Since HTMLParser is an old-styled object, any time you'd want to call a super-class defined method you would need to perform HTMLParser.superMethod(arg) instead of super(SubHTMLParser, self).superMethod(arg)


Creating the HTML parser
For the purposes of this example, I want something simple, so we're just going to take a block of markup and "tweak" all the <a> tags within it to be "sad" (whereas "sad" means they'll be bold, blue, and blinkey). The actual code to do so is only 50 lines long and is as follows:

  1. import HTMLParser
  2.  
  3. class SadHTML(HTMLParser.HTMLParser):
  4. '''A simple HTML transform-class based upon HTMLParser. All links shall be bold, blue and blinky :('''
  5.  
  6. def __init__(self, *args, **kwargs):
  7. HTMLParser.HTMLParser.__init__(self)
  8. self.stack = []


An informal poll at the Slide offices this past week yielded these interesting results: at Slide.com, nearly 100% of white people seem to like "Stuff White People Like".

I must say, I sure do like Arrested Development, not having a tv, expensive sammiches and diversity.

If you're subscribed to my RSS feed you wouldn't have noticed, but if not you probably already know by now about the change in the look of unethicalblogger.com. I got tired of the old (boring) red theme and dug around on drupal.org until I found one I liked and then customized it to suit my needs.

Other than that, I'm very proud to announce that this site is the 7th hit on Google for the query "unethical" (check it out). Besides the obvious tactics (kicking puppies), I'm wondering how I can reach the #1 result for "unethical".

Any ideas?

Since I've come from the land of desktop application development, there are a few concepts that I don't think quite "made the voyage" from desktop/thick-client development to web/thin-client development. The concept of "data binding" is completely lost in my opinion in the land of Javascript and HTML (not to mention the concept of "controls" to begin with).A few weeks ago while exploring a couple other concepts for how to improve our overall frontend development at Slide I prototyped a means of "databinding" controls, or at the very least DOM elements to data-providing Javascript functions.

I've posted an example here of some of the data binding code I've written for experimentation purposes. In the example page linked, there is a <ul> tag that is "bound" to a Javascript function, the Javascript function creates an array of associative arrays inline (it could very well be powered by some AJAX-oriented Javascript with minor adjustments). Using the results of the "databind" function specified on the bindable element, it creates a set of child nodes to attach to the parent list. In effect, the following code:

  1. <script type="text/javascript">
  2. var bindSimpleList = function() {
  3. var simple_list = new Array();
  4. simple_list.push({'contents' : 'List Item #1 OMG', 'onclick' : function() { alert("You clicked the first list item! lulz"); }});
  5. simple_list.push({'contents' : 'List Item #2', 'style' : 'border-bottom: 1px dashed red; width: 100px;'});
  6. simple_list.push({'contents' : '<strong>List Item #3</strong>'});
  7. return simple_list;
  8. }
  9. </script>
  10. <ul class="bindable" databind="bindSimpleList" databindto="li"</ul>
  11. </ul>
Will generate the following DOM tree, after the "bind()" function has been run on page load:
  1. <ul class="bindable" databind="bindSimpleList" databindto="li">
  2. <li onclick="alert('You clicked the first list item! lulz');">List Item #1 OMG</li>
  3. <li style="border-bottom: 1px dashed red; width: 100px;">List Item #2</li>
  4. <li><strong>List Item #3</strong></li>
  5. </ul>

Since the code is relatively simple (in my opinion) I figured I would throw it out there in all it's minimalistic glory and get some general feedback on the concept before I go "all out" and create a full-on jQuery extension based off of the linked prototype above. I'm trying to think of ways to make it more powerful as well, built-in support for binding to the results of an asynchrounous call to a URL that returns JSON that would then create the elements is at the top of my TODO list at this point. Feedback, flames and actual useful critiques are all welcome; I'll be sure to post again once I have the time to create the jQuery extension for binding, this however is more experimental quality (i.e. don't use it, i'm not).

What do you think?

With the release of Mac OS 10.5 (Leopard) I found myself in a tough spot, I liked certain features added into Leopard, but I couldn't stand some of the stability issues I was having and the other bugs that would interrupt my normal workflow during the day. In an effort to alleviate some of my frustrations with Leopard, I experimented for a week with running Gnome (with Compiz) on my openSUSE workstation. In general all the important bits were there, By this point, I had already switched from using any sort of GUI editor to work, but instead had switched over to using vim on a shared development server here at the office. Pidgin in Gnome Given that Drosera still wasn't fast enough for my normal day-to-day web development debugging, I was also using Firefox and Opera for most of my web browsing as well. Chat was covered by Adium, so using it's Linux/Windows counter-part, Pidgin was no trouble at all.

I've been doing work with OpenSocial recently and have used the opportunity to bring my tolerance talent in Javascript up a notch or two. In doing so, I've been slowly but surely running into a myriad of browser-specific quirks along with a few cross-browser gems that have left me thinking about putting some browser developers on my "To Anonymously Beat Up In Alleyway" list (so far, James Gosling, and this man top the list).

After working on a few "classes" tonight (the notion that Javascript is object-oriented still makes me chuckle) I ran into an interesting problem with some of my global-level "constants" defined in the same file that I was working in, that my "class" just so happened to make use of. As I tend to do when I fall into situations like this to where I can't tell if I'm hallucinating or if something with Javascript has gone awry, I called over Sergio (in-house CSS master and Javascript Lvl. 60 Mage).

Some background to how Javascript works
Javascript engines essentially have two "modes" that it runs over your code that you can spot errors in. The first mode, "parsing", is where you'll find syntax errors spewing into the Javascript console. If you've used any interpreted language before (Python, Java, C#, Ruby), this is really just "compilation". Using Python as an example, when you import a module (i.e. import some_module) the Python interpreter actually compiles your code into Python byte-code to be executed at a later date. The second mode, "execution", is where you'll run into your run-time errors, using an accessing an undefined object property, overrunning an array index, etc. In Python/Java terms, this is where your compiled byte-code is actually being run in the Python/Java virtual machine.

The gripe
The crux of the problem comes down to two different ways to declare an associative array in Javascript, the following two notations are both correct and both "work":
Notation #1

  1. var mapped_values = {};
  2. mapped_values['key'] = 'value';

Notation #2
  1. var mapped_values = {'key' : 'value'};

Everything looks correct yes? (hint: say yes)


I'm certain that this doesn't interest anybody in the slightest, but I just upgraded the entire site to Drupal 6.0.

Unfortunately some modules like jstools, or the Adsense module haven't been ported over yet so I've just gone ahead and disabled them for now until everything gets back to normal in the land of Drupal.

I've been very pleased with Drupal as a CMS, and am really look forward to them tightening up Drupal 6 further on in the release cycle, but right now everything is looking promising enough to jump ship from Drupal 5.xx.

In a vain effort to try to monetize all of the incredibly witty things that I do and say on this ridiculous excuse for a blog, I've started experimenting with Google AdSense mixed in with some of the content on the site. They don't insert themselves into the RSS feeds (as far as I know) and they only show up for anonymous users to the site so I'm willing to bet that the majority of where my traffic actually goes won't be affected.

Unfortunately, since Slide has infected me with this weird disease where I obsessively watch numbers, I'll most likely be obsessively watching a large number of zeroes in the coming weeks. That said, you could totally screw with me by clicking around on a lot of the advertisements...seriously, that would totally irritate me...you should try it.

This has been a whirlwind year for startups across the bay area and my startup, TY-Combinator really is no different. Barely a month into 2008, Slide, Inc announced it had received funding, the recent news about the bid from Microsoft to purchase Yahoo! for just above the GDP of Croatia and now great news for the TY-Combinator.

I'm pleased to announce that the TY-Combinator has received an unsolicited bid from Microsoft that values TY-Combinator shares at over 400% under market value. Microsoft is willing to offer TY-Combinator a half-eaten sammich in exchange for 85% of TY-Combinator outstanding shares. This is an exciting time to work for TY-Combinator, with the prospective addition of the capital Microsoft is willing to offer we will be able to finance new projects to expand our global reach over 1000%, up from our reported reach in the 2007 fiscal year of 1.


Microsoft's bid for a stake in TY-Combinator

I'm not proud of it, but I do read TechCrunch every now and again, if for only the occasional gem that comes across that causes me to hate buzzwords and everybody that uses them.

In the second paragraph of this article almost caused an entire system shutdown in my central-buzzword-processing unit (CBU):

"Both Imeem and Anywhere.FM saw a lot of synergy in the deal."

I couldn't read any further into the article after reading that, whenever anybody uses the word "synergy" seriously I have a tendency to tune out completely and think the absolute worst of them until they offer me chocolates, caffeine or other goodies.


At what point, as a man, do you give up hopes of being in a rock band?

A very long time ago I wrote about my backup script for archiving my entire Perforce repository. I can finally write the obvious follow-up to the post, as I've finally had to use my backups.

In my scenario, the last backup I took was in February of 2007, almost an entire year ago (my development slowed around that time). During my transit from San Antonio to San Francisco the "server" my Perforce repository ran off, also known as orange (seen on the bottom here), a "headless laptop", had its disk completely fail. Up until recently however I haven't had a replacement for "orange" but now that I have pineapple sitting in a colocation facility, I have a new candidate for a Perforce server.

Luckily I had made a habit of burning my backups to DVDs every two weeks, since two weeks of nightly backups would fill up an entire 4.7GB DVD (I still have no idea how my own source repository grew to 120MB or so). After rsync'ing the latest backup tarballs, it was completely up to Perforce to reliably restore them.

Perforce's documentation is very good, so I suggest going over the backup and recovery procedures if you find yourself needing to recover from backups.

Within about 15 minutes I had restored the Perforce database files as well as the actual source code itself and begun to sync a new Perforce client up with the new server (thanks to my p4tunnel script).

I can't talk enough about how much I really like Perforce as a version-control-system and am nothing short of elated to finally have my repository back online, it only goes to show how backups are crucial for anything you might ever want later, in my case backups albeit old backups, were still better than no backups.

I spoke with Tammy (our PR mastermind) about whether or not Slide was going to let me out of my cage to go to South by Southwest Interactive this coming March and it seems like they might actually let me! (I'm just as surprised as you are)

Unfortunately things with Facebook were at such a ridiculous pace when SXSWi was accepting panel submissions, that I never got a chance to submit my panel idea: "Slide is awesome, now let's talk about how great Slide is." This leaves me in a slightly awkward position, I cannot remember the last conference or event that I went to where I wasn't speaking or talking or dancing with a baboon in front of a live studio audience. Even at the last SXSWi I was there for about 36 hours and most of that time was spent setting up and then helping run BarCamp Austin2. Ideally I'd like to get on stage with some of the guys from Twitter, Facebook, Bebo, Google and maybe even Myspace to discuss the more open social web that we seem to be moving towards and a bit about how awesome Slide is. It's probably nothing more than a pipe-dream however, since the panels seem to be quite locked down at the moment.

Of course, if nobody will have me, then I might be relegated to slumming up and down 6th street in Austin hanging out with the usual drunkards that I know in Austin (you know who you are) and getting into trouble. Mmm, trouble.

Regardless, if you're going to be in Austin for SXSWi let me know, I've got a stack of swanky new business cards I want to get rid of :)

I had mentioned previously that iChatAgent in Leopard leaks, I'm going to take that statement back. iChatAgent in Leopard hemorrhages memory, and I think I know why now.

While I was napping, there was a network hiccup causing iChat to get disconnected, when the network connectivity returned, it first tried to sign on a couple of Jabber accounts, both of which use self-signed SSL certificates. Being the lovely old chap that iChat is it prompted the user (napping at the time) to accept the self-signed certificate. While the dialog box was up, iChat sat waiting around before it signed on the other accounts and spun and spun and spun.

iChat spun and spun and spun until all the available disk space for virtual memory was used up by every process that had to swap out to make space for iChatAgent's demands on real memory, and then by iChatAgent itself swapping out.

God fucking damnit.