Monday, March 18, 2013


Over the weekend, I've taken a little time to put up an application on Google App Engine (sorry, it's not public). Working with App Engine has been a very interesting experience so far. It's definitely not been business as usual, and I've a couple of bumps to prove it.

Here are some of the things I've experienced:
  • Trying to use the deferred library (a way to use push task queues without setting up URL handlers for them) without adding deferred: on in the builtins section of your app.yaml is a source of pain. Your tasks won't execute, and you'll keep wondering why.
  • If you have multiple versions of your app, you need to specify which one gets served as the default. I updated my app from version 1 to version 2, and was surprised that version 1 was still being served.
  • Sometimes, being able to download your application source is a boon.
  • Don't try to run searches on documents which don't have fields you're specifying. In my case, I changed generation of the documents for full text search to add one field, then updated the app. I began getting cryptic errors and was chasing red herrings until I logged in to the console and found the already indexed documents were missing the fields I was searching on.
  • It was a novel experience not being able to run an aggregation query like SELECT COUNT, because App Engine doesn't support such queries. If you want to count it, build your own counters for it.
  • Instead of using per-user namespaces for memcache, it might be a good idea to affix keys with the user ID of the currently logged-in user (for example, for storing query cursors when paging through results).
I'm sure there were other things, but it's almost 5am and I've been up for a couple of hours. Sleepy time.

Tuesday, March 05, 2013


in my current project, I'm using RapidSMS, and since it's based on Django, it comes with all of Django's testing capabilities, and adds a few. The TestScript class, in particular, is really nice. I've worked with .NET, Java, C, C++, JavaScript and even kicked around Objective-C a little, but this project is the first time I'm really doing serious unit testing (well, there was that one time I did behaviour-based testing for some JavaScript code for another project), and it's showing its value, even though:
  • It's boring. Seriously. I do not look forward to writing tests, but I'm doing it wrong, since I'm writing the tests after I've written the code. Maybe it's because of the way assertInteraction() works in RapidSMS that I think it makes sense to write the tests after.
  • It's eating time. Still, I'm beginning to feel the bite of victory when I see all those dots line up in a row after I do: test.
Last night, I did a little doodle in Sculptris while watching the Digital Tutors tutorial on Sculptris. It won't win any awards, but I'm beginning to see the attraction in digital sculpting. Since both Hexagon and Blender support sculpting, I think I can easily get my hands full. Speaking of 3D software, I can't remember what got me excited about the upcoming Wings3D 1.5 (no beta/RC for OS X yet — boo!), but I know good things are in store.

Oh, yeah. Take a look at power blade spam in Hexage's Radiant Defense:

Was wondering why GTBank has a lovely mobile site, but to use online banking, you still get to the desktop version of the site:

Plus, the site is Javascript-driven, which negates the use of what is arguably Nigeria's most popular mobile browser — Opera Mini. Take that keypad for entering your internet banking PIN, for instance. Good luck getting that to run with Opera Mini.
I'm not an Interswitch fan, but the company does some things right. QuickTeller now has a lovely mobile site (I haven't tested with Opera Mini, though), and have got over their paranoia by allowing you enter card PINs with an apparently regular text field on mobile.

I don't know how other people cope with using MTP devices, but I think the protocol sucks. For instance, the screenshots folder on my phone shows files with zero bytes. And when I tried copying the folder using Android File Transfer to my computer for this post, all the files had a size of zero bytes. And I cannot count how many times I've changed the filesystem on the phone, but AFT or Windows still shows the unmodified filesystem when browsing the device.

This is why I'm sincerely grateful for AirDroid. Here's the same folder as above in AirDroid:

Nonzero file sizes. AirDroid is a lovely piece of engineering. Well, that's all, folks!

Tuesday, February 26, 2013

Google Translate vs Human translate

Google-translated page (from German)

English version of text by page author
I say human translate wins.

Saturday, February 23, 2013

Looking at what goes in

Just this morning, I sat down to get some work done, and wanted to get a drink. I opened the fridge, and something like this greeted me:

I initially thought it was because I didn't get my glasses, but it's rather clear that most of the bottles of water have a decided blue tint to them. In fact, only the second bottle from the left on the top row – the one closest to the light – is unsealed. It's probably been refilled from the (faulty) water dispenser.

I'm not sure how the factory achieved the blue look, but I have to ask myself, is it really safe for consumption? And it's got me thinking a little more about what I take in, and not just in the way of food and drink, either. Who has my ear? What has caught my eye? What am I thinking about? And is any of it safe for consumption?

To be clear, I've nothing for – or against – the water bottling company. They just happened to be a (decidedly graphic) platform for the last paragraph.

Friday, February 22, 2013

Before you forward…

BlackBerry (or WhatsApp or ) broadcasts. Chain emails and text messages and instant messages. Status messages. Retweets. Modern technology is a wonderful way to let people know what we know (or at least, what we think we know). But sometimes, I wonder if we take the time to think about what we want to share before sharing.

You might have seen those status messages on Facebook where your friend says they want to stay privately connected to you. Or the BBM broadcast about cosmic rays from Mars. Or the message that Yahoo! servers are full, and unless you forward a certain message, your account will get deleted. Sadder still are the messages that say things like “For each person you forward this email to, XYZ Corp. will donate USD 0.01 to ABC”. I remember a tweet about an accident on the Third Mainland Bridge in Lagos, which I shared, and was later proven to be mostly untrue (the accident did in fact occur, but nobody ended up in the water).

It might be spitting into the wind and being overly obvious, but we really should realize that we shouldn't trust everything we read or hear. Some things are people's opinions. Some of them might be mistakes. Some, like this post makes clear, can just be from people taking advantage of other people's emotional responses to what they read (by the way, I think the post's author is making a very valid point).

At the very least, mention while sharing that something has not been verified. That should give people's natural cynicism a chance to kick in. And avoid blowing up (especially for effect) whatever you choose to share. If you heard that three cars crashed together, resist the impulse to exaggerate. When it's bad news, bigger is definitely not better. Panic over exaggerated claims often causes much more damage than the actual event itself (anyone remember the explosions in Ikeja Cantonment some years back?).

Wanderings, 2013-02-22

This post will contain "geeky stuff". You were warned.

Blender 2.66 released

Blender 2.66 was released yesterday. Some of the changes:
  • Cycles strand (hair) rendering;
  • Rigid body physics simulation (no more recording in the game engine!);
  • Dynamic topology;
  • New and more accurate particle fluid solver (I wonder why the new one is called the "classic" solver?);
  • Support for Retina displays.
You can view the release log here.

Lessons, failures and question marks at work

I've been working on a project that uses RapidSMS (and hence, Django), and I've had some ups and downs with it that I consider worth sharing. no longer works

If, like I have, you've used RapidSMS before (in the grand days of version 0.9.6a) and you're upgrading beyond that version, I've news for you (if you've never upgraded beyond that version): does not work anymore, at least for creating new projects. Go to the RapidSMS documentation site and read the installation instructions. Yes, I know: the documentation on setting up a new project shouldn't be under installation instructions, but we live in an imperfect world. Oh, and you'll need Django 1.4 or greater.

Python's extended slice syntax is all sorts of awesome when you need it

An example is much clearer than explaining:

>>> # a rather contrived example, but please bear with me
>>> mylist = ['a', 1, 'I', 'b', 2, 'II', 'c', 3, 'III']
>>> mylist[::3] # starting with the first element, pick every third element
['a', 'b', 'c']
>>> mylist[1::3]
[1, 2, 3]
>>> mylist[2::3]
['I', 'II', 'III']

Guido's time machine is alive and well. Don't ask what I needed this for, by the way. Oh, and if anyone has an excellent solution for displaying code snippets on Blogger, I'm all ears.

By myself, I broke Django's ListView (I think)

I set up a ListView for my project, but I kept getting an empty page, even after I confirmed that I had data in my database. Of course, when you have to communicate progress, an empty page isn't terribly convincing that you're not just sitting on your behind. After going back and forth with it, I decided to ask in #django on Freenode, and it was confirmed my code and template had correct code. After some more kicking stuff back and forth, it turned out that even though I had set the context_object_name on the class, Django was still going with the default, object_list. So if you set up a ListView and things aren't working as they should, this may save you a couple of head-scratching moments.

Blowing things up with syncdb and createsuperuser

I like my development environment. But sometimes, it can be really annoying. Every time I drop and recreate the development database for a Django 1.4 project, I'd naturally want to run syncdb to recreate the tables and whatnot. But on my development machine, the environment variable LANG is not set, which causes creating a superuser with the management script to blow up. There are a couple of fixes:
  • Set the environment variable before creating the superuser using the management script
  • Do a little code-jitsu to do that.
The second is my preferred choice, especially since a friend has drummed into my head the usefulness of having local settings in a file. So, by way of helping someone else, and in order to remember, I add these lines to my

import os

os.environ['LANG'] = 'en_US.UTF-8'

Found this fix on this Stackoverflow post (first comment on accepted answer). This has been fixed in Django 1.5, so until you upgrade, keep using the workaround.

Sunday, February 17, 2013

Unverified: Employment opportunity at Red Star Express

Location: LAGOS
The job:
- Comprehensive maintenance of all hardware
- Management of servers and internet connectivity
- Provide I.T support to all users
- Third party relationship Management
The candidate must have/be:
- B.Sc/HND Engineering (Electrical, Computer)
- Minimum of 3 years relevant work experience in a structured organization
- Basic oral and written communication skills
- Exchange server management skills
- Willing to travel.
- Ability to multi-task
- Age: 28 - 32years
Interested and qualified candidates should send their C.V (soft copy only) to  Multiple applications would be disqualified.
Application closes 21st February, 2013.
Only shortlisted applicants will be contacted.

The Perfect Mate

Got this from a newsletter, and decided to share:

A young lady visited a computer dating service and requested, "I'm looking for a spouse. Can you please help me to find a suitable one?"
The matchmaker said, "What exactly are you looking for?"
"Well, let me see. Needs to be good looking, polite, humorous, sporty, knowledgeable, good at singing and dancing. Willing to accompany me the whole day at home during my leisure hour if I don't go out. Be able to tell me interesting stories when I need a companion for conversation and be silent when I want to rest."
The matchmaker entered the information into the computer and, in a matter of moments, handed the results to the woman.
The results read, "Buy a television."

Men Only deodorant studio render

Still a work in progress. But I was dilly-dallying over completing it, so here it is. Yes, I know it's crap. Textures need major adjustment. No, it's different than the real deodorant body spray.

You might call it a revisit of one of these:

Wednesday, February 13, 2013

Naira MasterCard working on Amazon

One of the more pleasant surprises I got after migrating to a Mac was finding out that Apple has a localized store, and receives payments using local cards, or at lease the Naira MasterCard that's quickly becoming the de facto debit card here in Nigeria.

I also got a pleasant surprise wanting to pay for an Android app, and it turned out that Google Wallet also accepts payments using Naira MasterCard.

However, until last week, I avoided buying anything on Amazon, because Amazon had issues with local cards. In general, all my “purchases” on Amazon were books which were on “offer” (USD 0.00, just to be clear). However, last week, I missed getting one book that was free and had gone back to its original price, and wanted to at least get the sample. For some reason (habit, I guess), I clicked on the button to buy instead of the one to send the sample to my device.

I'd already added my card details, but never bothered to remove them from my Amazon account. I was initially appalled that I'd make such a mistake, but when I got the usual email from Amazon with the usual yadda yadda, I just hoped I wouldn't have issues with future “purchases”. When I later launched the Kindle app on my phone, instead of my purchase, I saw a book with Amazon's excuses.

But to my surprise, the payment actually went through, and my bank debited me. I've since gotten value for the payment, and apparently it still works, because I bought another book, and have got that too.

I guess this is good news for someone.