Google App Engine: Printing out all the Request Parameters

I figured out how to print all the request parameters in Google App Engine:

logging.info(self.request.params.items);

It looks like this:

bound method UnicodeMultiDict.items of UnicodeMultiDict([(u’A’, u’3′), (u’b’, u’4′)])

Along the way, I found useful information by making a dir() of the request object:

logging.info(dir(self.request))

[‘GET’, ‘POST’, ‘ResponseClass’, ‘__class__’, ‘__delattr__’, ‘__dict__’, ‘__doc__’, ‘__getattr__’, ‘__getattribute__’, ‘__hash__’, ‘__init__’, ‘__module__’, ‘__new__’, ‘__reduce__’, ‘__reduce_ex__’, ‘__repr__’, ‘__setattr__’, ‘__str__’, ‘__weakref__’, ‘_body__del’, ‘_body__get’, ‘_body__set’, ‘_body_file__del’, ‘_body_file__get’, ‘_body_file__set’, ‘_cache_control__del’, ‘_cache_control__get’, ‘_cache_control__set’, ‘_environ’, ‘_environ_getter’, ‘_headers’, ‘_headers__get’, ‘_headers__set’, ‘_host__del’, ‘_host__get’, ‘_host__set’, ‘_urlargs__del’, ‘_urlargs__get’, ‘_urlargs__set’, ‘_urlvars__del’, ‘_urlvars__get’, ‘_urlvars__set’, ‘accept’, ‘accept_charset’, ‘accept_encoding’, ‘accept_language’, ‘application_url’, ‘arguments’, ‘blank’, ‘body’, ‘body_file’, ‘cache_control’, ‘call_application’, ‘charset’, ‘content_length’, ‘content_type’, ‘cookies’, ‘copy’, ‘copy_get’, ‘date’, ‘decode_param_names’, ‘environ’, ‘get’, ‘get_all’, ‘get_range’, ‘get_response’, ‘headers’, ‘host’, ‘host_url’, ‘if_match’, ‘if_modified_since’, ‘if_none_match’, ‘if_range’, ‘if_unmodified_since’, ‘is_xhr’, ‘max_forwards’, ‘method’, ‘params’, ‘path’, ‘path_info’, ‘path_info_peek’, ‘path_info_pop’, ‘path_qs’, ‘path_url’, ‘postvars’, ‘pragma’, ‘query’, ‘query_string’, ‘queryvars’, ‘range’, ‘referer’, ‘referrer’, ‘relative_url’, ‘remote_addr’, ‘remote_user’, ‘remove_conditional_headers’, ‘request_body_tempfile_limit’, ‘scheme’, ‘script_name’, ‘server_name’, ‘server_port’, ‘str_GET’, ‘str_POST’, ‘str_cookies’, ‘str_params’, ‘str_postvars’, ‘str_queryvars’, ‘unicode_errors’, ‘uri’, ‘url’, ‘urlargs’, ‘urlvars’, ‘user_agent’]

logging.info(dir(self.request.params))

[‘__cmp__’, ‘__contains__’, ‘__delitem__’, ‘__doc__’, ‘__getitem__’, ‘__init__’, ‘__iter__’, ‘__len__’, ‘__module__’, ‘__repr__’, ‘__setitem__’, ‘_decode_key’, ‘_decode_value’, ‘add’, ‘clear’, ‘copy’, ‘decode_keys’, ‘dict_of_lists’, ‘encoding’, ‘errors’, ‘get’, ‘getall’, ‘getone’, ‘has_key’, ‘items’, ‘iteritems’, ‘iterkeys’, ‘itervalues’, ‘keys’, ‘mixed’, ‘multi’, ‘pop’, ‘popitem’, ‘setdefault’, ‘update’, ‘values’]

Patent: Portable Deaf Strobe / Vibration Personal Audio Triggered Deaf Notification Device

Sometimes I come up with an idea that I want to patent but I am so busy that I just blog it instead. Hopefully this will make it into the Internet Archive and folks can send me money when they want to license my invention.
This idea is pretty simple and my patent search (2 minutes on Google) suggests that while there are similar products, I cannot find this exact product.
The idea is to make a strobe light / vibrating system to alert deaf people when there is a particular noise from a set of noises in the room.
There are many similar products:
http://www.harriscomm.com/catalog/default.php?cPath=1215
It looks like you can nicely outfit a house for a deaf person to detect all kinds of things and signal them – even when a baby cries. But the products described above are not portable – they cannot be taken while traveling.
So my idea is a portable, self contained deaf alert system that “listens” actively for certain noises, loud speech, door knocks, crashing sounds, phone rings, etc.. It would even have a silent mode where pretty much any noise would trigger it – so while you were sleeping you could even notice a dor opening or closing.
You could even build a motion detector into the gadget to flash on motion.
The device could record audio to internal flash memory (probably only record when there is sound) – so that if something did happen – the audio could be downloaded and checked by someone who could hear. With compression and only recording when there are noises – several days would likely fit on 4GB of flash – of course there would be privacy issues with constantly recording stuff – perhaps the data could be encrypted – so special software would be needed to decrypt the audio. Maybe the audio files would need to be taken/sent/uploaded somewhere for analysis.
It might even be a good idea for non-deaf people to have such a thing – it would make them feel safer in their room while traveling.
Of course there would be some technical issues to train the gadget about which sounds to listen for – but I am betting this would yield nicely with the application of Genetic Algorithms and/or Bayesian techniques.
The gadget would need a pretty sophisticated configuration capability (although simple versions could be produced). They would likely need a USB connection to a PC for precise configuration and firmware upgrades. It would all a service technician to configure the system precisely for a less technically sophisticated device owner.
Building a prototype could be pretty easy – you just need a basic computer system with a sound digitizer and a light – frankly a One Laptop Per Child system could be used as a prototype. Perhaps some clever UM Engineering students could take this on as their project – I bet a prototype could be done in 15 weeks as long as sleep was not so important…

Saying: As a Parent, You don’t want your child’s education awarded to the low bidder

I was talking to Meghan Genovese about the new Informatics class and we were laughing about how those who predict the future of education are often off the mark. When it comes to our own education – we prefer the safe haven of bricks and mortar.
My funny retort was, “As a parent, you don’t want your child’s education awarded to the low bidder.”
Although seriously – within that notion (again as a parent) – I might award the contract for *part* of my child’s education to those who demonstrate that they teach better (regardless of cost) – and then award the rest of the contract for my child’s education to the organization which will help her be the best adult she can be and help her prepare for a diverse set of career paths and choices.
They say that one never can understand education well enough to affect the education of your own children. This is sadly true – because you only learn the right thing to do afterwards! Too bad I didn’t have like six children – I could then call the first two of them “proof of concept” and “prototype” – and after making all the mistakes on the first two – be spot on for the rest of them.

Morning Commute, Serendipity, GEOtagging Pictures, and Hot Coffee

At 7:28 AM, Lance Speelmon is hurtling through rural Indiana on Route 37 on the way to work – probably doing about 90 if I know Lance His random shuffle decides to pick a song that he and I listened to in New Orleans a long time ago – Bryan Lee and the Jump Street 5 – singing “Waiting on Ice”. Lance thinks of me and snaps this photo with his Blackberry iPhone and sends it to me:

At 7:47 AM I happen to be on line at home with a cup of coffee and see Lance’s picture/note. So I fire off a note saying hi with a smiley. Then I see the time of the note and fire off another note guessing that he is on his morning commute enroute to Indianapolis.
And then at 7:51, I idly wonder if his photo is GEOtagged. SO I pop it up in iPhoto and indeed it is and it was taken right here:

So he *was* on the way in to work – because his car was in the northbound lane.
Fun stuff.
At 8:00 AM, I went to Google Maps to use live satellite imaging to see if I could actually find where his car was on route 37. I quickly realized that we still have to wait a few years before Google puts 1000 cameras in low earth orbit to support live satellite imaging in Google Maps. So I gave up finding Lance on live satellite image (at least for now).
And then by 8:04 AM – I had written a blog post about it.
And then by 8:09 AM – I had a twitter about my blog post.
And then at 8:10 AM – I sent Lance a note with the URL of the blog post.
And then I went back to my coffee..
And it was still hot.
Update: At 8:15 Lance read my blog post and informed me that it was his iPhone 3G – so I fixed the post. But that got me thinking – does the 3G do Geotagging right when it sends pictures right from the phone… Now I finally might have a good reason to get the 3G.

Reinventing the Wheel – Stone-Simple PHP Object Relational Mapping (ORM)

Man is it fun to build stuff from scratch. About noon yesterday I was starting to write too much SQL – I have a user table that looked as shown below and I had a request object (also shown below) with lots of parameters that needed to go into the table. And I was going to have to this over and over for users, courses, tools, institutions, etc etc — Aargh. I love creative complex SQL – but Mundane SQL is not fun at all – because it is bug prone.

Friday night I asked Noah which PHP ORM he liked – we went through about 8 existing PHP ORMs (mostly over-imitating Rails) over IM and SMS. Each one he brought up – I decided it just sucked because it was too complex and required me to hack my PHP installation so bad and change my development style too much. What I wanted was effectively 80% of the features of ActiveRecord with one single PHP file that I would require_once at the beginning of my file and I could hack SQL when I wanted and use the ORM to do the nasty, dirty work.

So in the past 24 hours I developed my own PHP ORM – here are the features:

  • It does not need any hacking of PHP
  • It is unit-tested – using the unit test framework I built yesterday
  • It is one simple PHP file that you include in your source code
  • It uses ActiveRecord conventions (id, created_at, updated_at), etc.
  • It is infinitely hackable – you can step right around it if you like
  • It did foreign keys like ActiveRecord institution_id
  • It required ZERO configuration except for the table existing with some columns – no XML configuration – zip zero none – nada
  • It adapts to changes in the table trivially – if you add a column – the object knows about the column.

So here is a bit of sample code to use my ORM:

require_once("orm.php");
$usr = new ORM("user", "userid", "lti_user");
$userid = $_REQUEST[user_id];
$usr->read($userid);
$usr->setall($_REQUEST, '/^user_/');
if ( $usr->id() ) {
$usr->update();
} else {
$usr->insert($userid);
}

It is pretty Rails-like – the read() either loads the existing record or not. The setall() takes an associative array of key/value pairs (optionally limited by a regex) and updates all the fields in the object. The setall() has optional soft field matching (on by default) so the request fields don’t have to be identical to the database fields. If the object was loaded, id() exists so we update() otherwise we insert(). On the second and following ORM() call the key and table name are not needed. You can also load the ORM prior to the construction of the first model for error checking earlier.

The ORM code is 352 lines of PHP with a 152 line unit test. There is a little more work to do. But for now it works well enough for me to get back to writing my IMS LTI application without building large amounts of nasty, repetitive SQL.

The beauty of Rails and ActiveRecord is that it shows us how to build an ORM – in a sense – the ORMs of the future can assume all the thinking that went into Rails and then find new, cooler places to go – and perhaps to do so cleaner and better – and further evolve the breed.

Here is the table:

create table lti_user (
id MEDIUMINT NOT NULL AUTO_INCREMENT,
userid CHAR(255) NOT NULL,
eid CHAR(255) NULL,
displayid CHAR(255) NULL,
password CHAR(255) NULL,
firstname CHAR(255) NULL,
lastname CHAR(255) NULL,
email CHAR(255) NULL,
locale CHAR(255) NULL,
institution_id MEDIUMINT NULL,
created_at DATETIME NOT NULL,
updated_at DATETIME NOT NULL,
PRIMARY KEY (id)
);

Here is a dump of the request object:

Request Dump
Array
(
[action] => direct
[sec_digest] => 8PCloWWp4brpvuSylfyn8SaoTF4=
[sec_org_digest] => 8PCloWWp4brpvuSylfyn8SaoTF4=
[sec_nonce] => f6348bcf-87f8-11dd-b7d8-552f83eeb0b4
[sec_created] => 2008-09-21T16:18:44Z
[sec_secret] => secret
[user_id] => 0ae836b9-7fc9-4060-006f-27b2066ac545
[user_role] => Student
[user_displayid] => csev
[user_firstname] => Charles
[user_lastname] => Severance
[user_fullname] => Charles Severance
[user_email] => csev@umich.edu
[user_locale] => en_US
[user_roster] => SI300-010-F08
[course_id] => 8213060-006f-27b2066ac545
[course_code] => SI300-001-F08
[course_name] => SI300
[course_title] => Social Computing
[org_id] => umich.edu
[org_title] => University of Michigan (CTools)
[org_name] => UMich
[org_url] => https://ctools.umich.edu
[launch_resource_id] => 27b2066ac545
[launch_targets] => widget,post,iframe
[launch_resource_url] => http://www.dr-chuck.com/
[launch_tool_id] => sakai.lti.168
[launch_tool_name] => Video
[launch_tool_title] => Video Review for Midterm
[launch_width] => 320
[launch_height] => 240
[camtoolspref] =>
)

Chuck *has* learned a little bit in the past five years

I am pretty happy with myself – in the past five years – I have learned the importance of unit testing. Here I am hacking at my NG LMS based on IMS Learning Tool Interoperability – and instead of just writing a ton of code, I first spend two hours and wrote a PHP unit test framework so I could unit test all of my PHP utility code. It is pretty cool – it makes it so you don’t have to keep pressing REFRESH when you write code and also when you write debug code to exercise code – you just keep it in a unit test as well. I also wrote a PHP logging/debugging mechanism – so I don’t have to keep printing out stuff and then commenting out the prints – the logging automatically gets verbose during unit tests.

Part of this is that I miss Rails – I liked the fact that you could write less mainstream code and fall back on Rails conventions for stuff. Now you might ask – which not use a Rails clone like Ignitor or a bunch of others – the problem with those is that they are too big. I want something that gives me functionality with a single require_once() in my code – and that the distribution is a single or a few PHP scripts and not a BUNCH of hacking on my PHP installation. I want it clean and simple and a natural extension to basic PHP work patterns.

So I have progressed to understanding the importance of Unit tests but have not yet gotten to the point where I am willing to pull in a terabyte of some other framework. Ah well.

Here is sample output:

======Running Unit Tests for ALL-Tests
===Running Unit Test:ALL-Tests function:unittest_debug_01
Line 1
Line 2 <tag>
=============
Line 1
Line 2 <tag>
=============
Line 1
Line 2 <tag> ===Running Unit Test:ALL-Tests function:unittest_debug_02 Line 1 Line 2 <tag> ===Running Unit Test:ALL-Tests function:unittest_nonce_01 2008-09-20T15:22:27Z 9423067 3600 Expired ===Running Unit Test:ALL-Tests function:unittest_nonce_02 Presha1 5a10e285-6a52-4dc6-816b-d917c28302692008-06-03T13:51:20Zsecret postsha1 zhA0wHlwZaavrEIUw0wNPlTR3PQ= digest zhA0wHlwZaavrEIUw0wNPlTR3PQ= Match ===Running Unit Test:ALL-Tests function:unittest_nonce_03 Presha1 5a10e285-6a52-4dc6-816b-d917c28302692008-06-03T13:51:20Zsecret postsha1 zhA0wHlwZaavrEIUw0wNPlTR3PQ= digest zhA0wHlwZaavrEIUw0wNPlTR3PQ= Match ======Completed unit tests for ALL-Tests Result: PPPPP

Saying: Rome was prototyped in a Weekend

I was talking with by buddy Rich on the phone this morning and he was teasing me about trying to write the next generation LMS in a weekend. Last weekend I wrote the client side prototype and this weekend I am writing the server side prototype.
He laughed at my silliness and said “Rome was not built in a day” – my quick retort was “Rome *was* prototyped in a weekend.” He thought it was funny – so I blogged it.

Home Technology Upgrades

Well sooner or later some hardware has to be upgraded. I got some stuff I really like.
New Laptop
Since Mandy is off to college at MSU – and she called me and mentioned that her laptop needed reformatting (again) since it was slowing down – I splurged on a new MacBook from the Michigan Computer Showcase. It was a great price – $1299 – including 2GB RAM and 3 years of Apple Care – and a free (with rebate) iPod touch. Someone will the the touch as a gift probably. I also bought two licenses at faculty price of WIndows Vista – I will try to avoid giving Mandy Vista (shhh don’t tell her) as long as possible – not that I don’t like Vista – I actually really like a VIsta a lot – I just want a mono-culture of operating systems. This frees up Mandy’s AMD based laptop – I might end up with my own PC laptop out of the deal after things shake out and I give myself Brent’s laptop.
New Printer(s)
I finally retired the LaserJet4 printer – it was a workhorse – but it did not have a power save mode and it just bothered me to be paying to both heat and cool the house all summer long.
I almost went and got an HP Color Laser – HP makes a nice one for about $400 – but this time – I did not rush – and I googled – before the purchase (instead of after the purchase) – it turns out that the color cartridges need replacing even if all you do is print black and white – sorry HP – that does not compute for me.
So my next printer choice was the Brother 2170w – for a little over $100 you get a fast compact B/W laser printer – with wireless and wired networking – and from my previous Brother experience – I knew that I loved their approach to strong mac support and Vista support.
I decided to buy it on Amazon because I missed the sale at Office Max – and the printers were $80.00 – I figured – Heck! That is about the cost of a toner cartridge – so I bought two so the kids have their own printer – and when one toner runs out – we have a whole spare printer! I worried a bit about having three Brother printers on the same network – but figured Brother had that figured out.
I was going to wire the printers instead of wireless – but once I experimented with wireless – I skipped the wires. Here is the pattern – you connect the printer to the network – install the drivers. You can reconfigure the printer using the BRAdmin lite software (Windows only – good to have Vista dual booted on the family mac). It scans the LAN and finds the printers – and you can tell them to become wireless printers. I have a nice Airport Express with security on the second floor – so they get strong / fast signal. You give the WEP password – viola! You have a wireless printer.
All the printer drivers – I installed as Ethernet – not wireless – after all the printers just have IP addresses.
On the Mac you just add a printer – when there are multiple printers the list of printers (Bonjour) appends the Mac address to the printer name – so you can figure out which one you are talking to. On Windows – the add printer did not work to find the printers on wireless so well – so I used BRadmin to find the printers and then just told Windows to look at the right IP address – from that point forward printer install was trivial and obvious.
I ended up putting both printers on wireless – since it is so dang fast and so seldom used – it is just two less wires tangling under our feet. And the printers can go anywhere there is a power plug – very nice.
So now we have three networked Brother printers – inkjet and two lasers all on the network and working on all my operating systems in the house.
Summary
This felt really good – my goal as CTO of the home is to keep tech support calls o a minimum – my approach is to fix problems before they occur – things like two internet connections (cable modem and DSL) and an auto-failover router. I have just learned over time that network attached printers are the only way to go – and that you need a lot of printers – because they will fail at the weirdest time – sometimes it is technical and sometimes it is supplies. But in all cases – I am far away from home – it is 12:30AM and there is a major homework project due tomorrow morning.
Moving toward an all-Mac computing environment and everyone either having an iPhone or iPod – also makes things nice – iTunes libraries work well and share well (with Apple TV too) – and we have lots of charger cables for iPods and iPhones laying around the house.
So this time next year when Brent graduates from High School – there will likely be one more Mac laptop purchased. After that I will simply have to get another more iMac that dual boots in the basement – and I will be 100% mac hardware in the home.
Vista and XP will be present where folk need them – but as I pointed out in a blog post – Mac seems to support Vista and XP better than most PC-only hardware vendors.

I found the CENTER tag in CSS

I have been hating on CSS because I can’t use the center tag. It is like – just CENTER it DAMN it!
Here is the magic bits:
http://archivist.incutio.com/viewlist/css-discuss/44878
/* Helps IE to center. */
div#outerdiv {
text-align: center;
}
/* The margin version for real CSS savvy browsers. */
div#div_to_be_centered {
text-align: left;
margin: 0 auto;
width: 650px;
padding: 0; /* Zero to prevent IE box trouble. */
}