the further adventures of

Mike Pirnat

a leaf on the wind

Next Page »

Announcing Procatindex

Replacements

If you're even a little bit like me, you think Procatinator is one of the Internet's greatest achievements. (If you don't know Procatinator, pop on over there for a minute or two and you'll know whether the rest of this post is for you or not.)

If, like me, you have favorite cat GIF/music mashups but can't recall their exact URLs when you're trying to wow your friends, then my latest silly website project is for you.

Behold: the Procatindex!!

Procatindex.com keeps a list of all the Procatinator cats, with titles pulled from the music videos used. The list is automatically refreshed when there's a new cat, and you can subscribe to the RSS feed to make sure you never miss the latest additions.

The site and the script that refreshes it were built in a couple of hours with Requests and Flask, which made short work of the task. (If you aren't familiar with these, you should check them out. Though I have mixed feelings about Flask, it's a wonderful go-to for quick web apps like this. And Requests has become something I can no longer live without.)

Hopefully this improves the effectiveness of your procatination. Enjoy!

Read and Post Comments

240/365: World's Yummiest Drum Solo

240/365: Drum Solo

My boss scored a few MaKey MaKey kits from their Kickstarter campaign and distributed them among the office to see what creative things we'd find to do with them. My cube neighbor Dave Noyes wired up a food-based drum kit--bananas as toms, lettuce as hi-hats, a red pepper as bass, and a slice of bread as the snare, all played with a pair of celery sticks.

In this photo, we find our coworker Julie being surprised and delighted by playing with this unorthodox setup.

Later, once all the inputs were rigged up, I convinced Dave to drum along with a NIN tune:

I think it's safe to say it might be one of the best Monday afternoons of all time.

Read and Post Comments

Welcoming the Webble

The Upgrade

After a couple years of having no footrest for my home desk, then trying a now-defunct subwoofer, and about two months of relative satisfaction with a small Amazon box, I finally decided to indulge my ergo urge and sprang for a Webble, an effortlessly-gliding, four-castered footrest that resembles a mesh-covered Pringle. It's taken me this long to write up a review because I've been too busy not being uncomfortable while working on other projects.

The short version? It took some getting used to, but now I'm sad that I don't have one at work.

Since the Webble is a bit thicker than the cardboard box it replaces, I had to raise my chair a bit in order to make my knees feel right. This has emphasized certain other ergonomic problems in my current chair (a POS from the Office Max up the road that's got to be close to 10 years old at this point), which means now my upper body wants to be spoiled too. It also doesn't feel cquite right when I'm wearing shoes, but I think that's because my proximity to the wall means that I can't quite put my feet where I'd like to with shoes on.

In sock feet or bare feet, though, it's just about perfect. I alternate between using the front edge, the top sides, the top ridge, and the open mesh area in fairly equal measure, shifting naturally whenever one of my legs wants to move. I also find myself partly rotating it quite a lot, and quite often I'll absentmindedly spin it around or pop it up like a skateboard. I find myself really missing it at work, where I use a static footrest that helps but isn't nearly as much fun as the Webble. Plus it looks a lot classier than a cardboard box.

If you spend a lot of time in front of a computer, little comforts can go a long way toward improving how your body feels; you could certainly do worse than this delightful companion.

Read and Post Comments

Unhijacking Alfred's Google Searches

My ISP hijacking a Google search

I'm pretty much in love with Alfred; it's usually the first thing I install on a Mac. For whatever reason, though, I rarely use it to fire off Google searches, usually going straight to my browser. But today I fired off a search from Alfred and was aghast to see a crappy hijacked results page from my ISP, who I'd previously praised for having a fairly mature attitude toward all things internet and not requiring me to have TV service with them. I think I invented at least three new, wildly-offensive swear words when I realized what was happening.

Now, my ISP hides a tiny little opt-out link in an area of the page that, is virtually invisible due to its proximity to what my brain perceives as pure garbage. (In fact I'd written most of this before I even noticed it was there at all!) But you might not be so lucky, or, depending on the way the opt-out is implemented, you might not stay opted-out, and anyway, isn't a clever DIY solution more fun?

Since Alfred just makes a URL and hands off to the OS's preferred browser, I fired up Charles to see what was going on. Sure enough, they're intercepting GETs to http://www.google.com/search?q=whatever and throwing back a 302 to their own, crappy search, and I was able to quickly duplicate the behavior in my browser by cooking up the same form of URLs.

But why hadn't I noticed this before, using the search box in Safari, or by going straight to Google first? The reason is that my ISP's pattern-matching is delightfully naïve, so it doesn't catch the richer URLs that Google or Safari construct. This gives us the key we need to craft a workaround for Alfred: a custom search!

Custom searches are the cat's pajamas--I've rigged up a bunch for work to quickly drop me into our wiki, issue tracker, and so forth. Rather than waiting for the Alfred developers to provide a fix for the search hijacking, we can make our own custom search quickly and easily.

First, start by disabling the default Google search in Alfred. Open up its preferences, navigate into "Features", then "Web Searches", and then uncheck the Google checkbox:

Turning off Google search in Alfred preferences

Next, select "Custom Searches" and click the "+" to create a new one. You can then monkey with the URL to slip past The Man--for example, a simple alteration to the query string like http://www.google.com/search?&q={query} can do it. In my case, I chose to make the simple switch from HTTP to HTTPS, as it's likely to be more robust and gives me a nice, encrypted channel.

Creating a custom Google search for Alfred

To get the same nice logo that Alfred's default has, we can go get the icon out of the app itself. Right-click (or control-click) Alfred.app in your Applications folder and select "Show Package Contents". Then open the "Contents" and "Resources" folders and you'll find all of the icons. Find the "google.png" image and drag it over into the icon drop zone in your custom search.

Finally, we need to wire our new search into Alfred's "Fallback Searches". Pop open the one that's currently set to "Search Google for '...'" and scroll down to the bottom, where you'll find the custom search below a separator:

Replacing Alfred's fallback Google search

And that's all there is! Alfred is restored to full Google-searching glory. I'd like to say a huge thank you to the developers of Alfred for providing the flexibility that made this not only doable but easy. Huzzah!

Alfred searches Google, as it should be

Read and Post Comments

Configuring Wordpress SSL Login and Admin on Webfaction

image: bike covered in bike locks

I finally got fed up with not having SSL for my Wordpress instance on Webfaction and decided to rectify it today. I ran into a couple of surprises along the way that were really irritating, so once I sorted them out I figured I owed the internet an explanation so that things would be easier for anyone else wanting to do the same thing.

Assumptions

I'm going to assume that you already have a Webfaction account with a Wordpress instance running on it. If not, the control panel screencast is an oldie-but-goodie that'll get you started. I'm also going to assume that you're on one of the basic, shared hosting plans, and that you'll be running your secure stuff on the same box as your non-secure site. And I'm also assuming that you'll be okay using Webfaction's default SSL certificate rather than your own--this will throw warnings in many browsers, but saves you the cost of purchasing your own cert and the time required to request a private IP from Webfaction. And this only applies to Wordpress 2.6 and above. (You really should upgrade, you know.)

Create a secure site

In the Webfaction world, a single "site" can only be non-secure or secure, so you need to create a new site that will largely mirror your existing, non-secure site. To do this:

  1. Log into the Webfaction control panel.
  2. From the Domains/websites menu, pick Websites.
  3. Click the little green + icon at the bottom-right of the websites panel to begin creating a new site.
  4. Give your new site a meaningful name (I like it to be the same as the non-secure site, but with "_secure" or something similar tacked onto the end).
  5. Choose the same IP as the non-secure site that you're adding SSL to. Unless you are fancy enough to have multiple IPs, this shouldn't really be a choice at all.
  6. Check the HTTPS checkbox. (This is important.)
  7. Choose the same subdomains as the non-secure site that you're adding SSL to--so if your site is at http://www.yoursite.com, you might want to make sure that you select yoursite.com and www.yoursite.com subdomains so that both will be connected to this configuration.
  8. In the Site apps section, add your existing Wordpress instance with the same URL path that it has in your non-secure site. If you've got an app called my_blog at /blog, make sure you do the same thing here.
  9. Click Create.

Fix your Wordpress URL configuration

If you visit your blog now (in non-secure/http mode), depending on your browser, you might see a complete and total failure to load your stylesheets--meaning that your site is now probably fairly ugly. If you view source, you'll see that, even though you aren't loading your page from over HTTPS, Wordpress is generating HTTPS links for all your content--stylesheets, images, everything.

To fix this:

  1. Log into your Wordpress instance and go into the Dashboard.
  2. Go to the General Settings page.
  3. Change the WordPress address (URL) and Blog address (URL) fields to begin with http instead of https.
  4. Don't forget to Save Changes.

Now try your site on its non-secure/http link. When you view source, all your resources should be coming from URLs that start with http.

Update your wp-config.php

Edit your wp-config.php. Depending on what you want to do, you'll add one or the other of the following two lines.

To require only login to be secured:

define('FORCE_SSL_LOGIN', true);

To require login and admin pages (my preference) to be secured:

define('FORCE_SSL_ADMIN', true);

Profit!

Log out of your Wordpress instance, then hit your login link. You should now see that your login and registration pages are served up via https links. If you chose to use FORCE_SSL_ADMIN, you should also see https in all of the URLs as you navigate around your Wordpress admin area.

Things should be hunky-dory now. I hope it worked out all right for you!

Read and Post Comments

Atomisator Configuration for Unified Python Planet

Robert Kern asked me to share my Atomisator configuration for the Unified Python Planet. So, here it is:

[atomisator]

# sources
sources = 
    rss http://www.planetpython.org/rss20.xml 
    rss http://planet.python.org/rss10.xml

# filters
# "doublons" is French for "duplicates" --  this is what de-dups the feed
filters =
	doublons
	
# enhancers
# I'm not using any, just leave this blank (default)
enhancers =

# outputs
outputs =
    rss /home2/mpirnat/webapps/pirnatwp/static/unified_python_planet.xml "http://feeds2.feedburner.com/UnifiedPythonPlanet" "Unified Python Planet" "A uniqued union of the Official and Unofficial Python planet feeds.  Generated by Atomisator FTW!" 

# database
database = sqlite:///atomisator/unified_python_planet.db

The example configuration files that come with Atomisator are really good at illustrating how you would use them; I've omitted the explanatory comments from my example, but they're in the examples and will point you in the right direction. Thanks again to Tarek for this very handy tool!

Read and Post Comments

The Diaper Pattern Stinks

I mentioned the "Diaper Pattern" in a recent post and got some comments asking what the term meant. I had hoped to just link to an explanation, thinking it was a well-known antipattern, but several minutes of frustrated Googling have left me convinced that there's actually a tiny knowledge gap to be filled here.

"Diaper Pattern" is a term that I picked up from working with Matt Wilson and David Stanek. It's an anti-pattern about naively over-broad exception catching. A very basic example in Python might be:

try:
    do_something_that_might_throw_various_exceptions()
except Exception:
    pass

If anything at all goes wrong in do_something, the except will catch and silence it--but we know that errors should never pass silently (unless explicitly silenced). It's called a Diaper because it catches all the shit.

In practice, unless you have a good reason to catch everything, it's a lot better to only catch the specific exceptions that need special handling, so that you'll know right away about any runtime surprises and where they came from:

try:
    do_something_that_might_throw_various_exceptions()
except IOError, e:
    # handle just IOErrors; let everything else make noise

Maybe it's just a coincidence, but I've heard the term used more by developers who have young children than by those without kids.

Read and Post Comments

The Zen of Doing It Wrong

A coworker unearthed this little treasure today... I think it's a vestigial structure to assist Diaper (anti)Pattern treatment during testing or debugging, but it's still gross to see it in real, live production code. (Oddly enough, I couldn't find a good "Diaper Pattern" link whilst Googling about--surely I'm not the only one who uses this term?) Anyway, without further ado:

try:
    os.remove(filename)
except:
    raise
    pass
try:
    os.remove(os.path.join(TMP,'out-%s' % base_filename))
except:
    raise
    pass
try:
    os.remove(os.path.join(TMP,'properties_%s.lock' % brandid_human))
except:
    raise
    pass

If an exception is raised, raise an exception... It has a certain zenlike beauty to its awfulness. The use of the Diaper Pattern is bad enough, but this guarantees blowouts!

Read and Post Comments

A More Excellent Unified Python Planet

Good news, everyone!

After a couple days of playing Twitter tag with Tarek Ziade, we finally met up for lunch at PyCon, where, in addition to having a lovely conversation, he was kind enough to give me a personal tour of his Atomisator framework for data aggregation.

Atomisator is much savvier than Yahoo Pipes at things like removing duplicates and not mangling content, so I've kicked Pipes to the curb and hooked up the Unified Python Planet feed to my Atomisator output.

What this means for you, lucky reader, is that everyone who subscribes to the Unified Python Planet should not only stop getting duplicates, but, more importantly, have legible code samples directly in the feed. (It's okay if you need to take a moment to process this joyous news. It makes me pretty damn happy.)

Please let me know if you experience any flakiness with the new, improved feed.

I want to give major, major thanks to Tarek! Atomisator is really well suited to this purpose, as well as some other stuff I'm now curious to tinker with.

Read and Post Comments

Well That Was No Fun

Thought I'd be all spiffy and upgrade to the shiniest new Wordpress tonight. I did my little svn switch/bzr add/bzr merge trick to get all the new files in the right place, upgraded the database, and felt pretty awesome... Then my blog started throwing miles upon miles of "transport errors" and 500s, as did a couple others that I hadn't even touched with upgrades. The common factor seemed to be WP instances that were nested off of subdirectories of one of my domains, rather than WP instances at the root level of the domain. That smells like some kind of configuration problem in Webfaction panel-land, but I was too impatient to open a ticket (and trying to focus on something, anything other than Mama Mia that my wife was watching), so I ended up doing a mysql dump, blew away my old blog instance, dropped a new one into place (which magically worked, thanks a lot, universe), and restored from my backup.

So... Upgrade done (good) but not how I planned it (bad).

On the plus side, I was kind of getting sick of the theme anyway. :-P

Read and Post Comments

Next Page »