whatspop


A log of interesting things made by Kunal Anand

Flock of Alfreds

06/04/2009

I spent 10 minutes with Python, Quartz2D, Illustrator, and Photoshop to create a background for my Twitter profile.

First, I started by visualizing a flock of Alfreds using Quartz2D. The Alfred doodle is an SVG file where individual paths are randomly mutated within bounds; the output is the maximum resolution of a 30 inch monitor.

Alfred - Step 1

Then, I brought the flock into Photoshop and blended several radial gradients:

Alfred - Step 2

Finally, I added typography:

Alfred - Step 3

You can check out the final product on my Twitter profile (jankybear).

OK

06/03/2009

In between stress waves and crazy hours, I created another mixed media piece called "OK":

OK

"OK" was created while listening to Radiohead's OK Computer and was more involved than the previous pieces. I painted with sponges and plastic bags instead of brushes. It was such a messy experiment - I'm still trying to scrape acrylic paint from my fingertips.

With five unique pieces, I feel that the "Things I See In You" series is complete.

Moving a Blogger blog to Google App Engine

06/01/2009

I took the plunge and moved all my domains to Google App Engine this weekend. Migrating whatspop.com, a remotely hosted Blogger blog with project pages, was an interesting challenge. What follows are the highlights of the process.

Redirecting non-blog related content

In the spirit of being a single serving site, I decided to move all non-blog content off whatspop.com. An example of non-blog content is the project page for the ColdFusion Technorati API - whatspop.com/technoratiapi. I ended up redirecting requests for these respective artifacts to a valid location on kunalanand.com.

Here is how the redirection is accomplished:

class GZeitgeistProjectHandler(webapp.RequestHandler):
  def get(self):
    self.redirect('http://www.kunalanand.com/gzeitgeist/')

class GZeitgeistFeedHandler(webapp.RequestHandler):
  def get(self):
    self.redirect('http://www.kunalanand.com/gzeitgeist/gzeitgeist.rdf')

class TechnoratiApiHandler(webapp.RequestHandler):
  def get(self):
    self.redirect('http://www.kunalanand.com/technoratiapi/')

def main():
  application = webapp.WSGIApplication([
    (r'/gzeitgeist/?', GZeitgeistProjectHandler),
    (r'/gzeitgeist/gzeitgeist.rdf', GZeitgeistFeedHandler),
    (r'/technoratiapi/?', TechnoratiApiHandler)])
  wsgiref.handlers.CGIHandler().run(application)

The '/?' at the tail of the regex is to catch the optional forward slash - previously a project page was a default document within a directory and IIS added the forward slash.

Moving the blog

I started by using the Python GData API to extract all of my blog posts. Here is a snippet of creating objects from the GData feed:

entries = []
feed = self.service.GetFeed('/feeds/' + self.blog_id + '/posts/default?max-results=100')

for entry in feed.entry:
  entries.append(Entry(entry.title.text, entry.published.text[0:10], entry.content.text))

If you don't specify max-results then you'll have to use an offset variable to paginate. In my particular case, I had less than 100 posts and decided to get everything at once. The next step was to transformed and cat the entries to a massive HTML dump:

python blogger_post_snagger.py > all_blogger_posts.html; open all_blogger_posts.html

I used this opportunity to prune and edit older content. Massaging these posts involved:
  1. Improving the quality of writing
  2. Moving images to Flickr and videos to Vimeo
  3. Keeping track of original Blogger slugs
These changes required a lot of patience and consumed 80% of the total time. Once the munging was done, I started off by creating an Entry object:

class Entry(db.Model):
  title = db.StringProperty(required=True)
  body = db.TextProperty(required=True)
  blogger_slug = db.StringProperty(required=False)
  appengine_slug = db.StringProperty(required=True)
  published = db.DateTimeProperty(auto_now_add=True)
  updated = db.DateTimeProperty(auto_now=True)

After that, I created some routes:

def blog():
  application = webapp.WSGIApplication([
    (r'/', MainPageHandler), 
    (r'/blog(/?)', OldBlogRouter),
    (r'/blog/[0-9]+/[0-9]+/([^/]+)', OldBlogPostRouter),
    (r'/fortress', FortressHandler),
    (r'/fortress/new', NewEntryHandler),
    (r'/fortress/edit/([^/]+)', EditEntryHandler),
    (r'/fortress/delete/([^/]+)', DeleteEntryHandler),
    (r'/archive', ArchiveHandler), 
    (r'/feed', FeedHandler),
    (r'/entry(/?)', ArchiveRouter),
    (r'/entry/([^/]+)', EntryHandler)])

One of the trickier challenges was to redirect old Blogger permalinks to new ones. The Blogger blog had permalink slugs that looked like: whatspop.com/blog/2009/05/nine-doodles.cfm. Requests that match the old permalink are dispatched to the OldBlogPostRouter:

class OldBlogPostRouter(webapp.RequestHandler):
  def get(self, slug):
    entry = db.Query(Entry).filter('blogger_slug', slug).fetch(limit=1)
    if len(entry):
      self.redirect('/entry/%s' % (entry[0].appengine_slug))
    else:
      self.redirect('/archive')

If the blogger_slug exists then redirect to the updated url; if it does not then redirect to the archive.

I built an administrative interface for adding/editing/deleting posts called "Fortress" - yep, it's a Superman reference. Fortress is minimally styled scaffolding that isn't too interesting to share.

Other eccentricities

Here are some things that are worth mentioning: I must praise the team working Google App Engine - it's a simple and stellar platform. I look forward to trying out the Java/Scala App Engine API.

Nine doodles

05/27/2009

Jankybear - First Nine Characters

If you've been following this blog, you'll know that I've been actively doodling for the past few months. The above represents nine of my favorite characters - expect the next installment over the next few weeks.

Mystery Science Theater 3000 bookmarklet

05/03/2009

For some strange reason Mystery Science Theater 3000 has popped up in various conversations over the past two weeks. Thanks to a vector provided by a user on DeviantArt, I was able create a bookmarklet that adds Crow, Joel/Mike, and Servo in the silhouette form to the bottom of your browser window.

Here are some screenies in action:

MST3K Bookmarklet - Vimeo

MST3K Bookmarklet - Twitter

Want the bookmarklet? Drag this link to your bookmarks menu/toolbar.

It's important to note that the silhouette might look borked on some sites. This is typically caused by margin/padding offsets created by a site specific stylesheet. If you figure out a way around this (nuking the styling of the page is not an option) then send me an email.