I don’t normally write about technical development topics, but today I’m making an exception, because finding the source of my problem was incredibly difficult. I’m hoping that this post will serve me in the future when I inevitably come across this problem again.
For the university assessment I’m working on at the moment, I have to use the web2py Python framework to create a web application. Part of the framework allows you to create and process HTML forms, including performing validation on the user’s input.
The problem I had today was that I was using a form, and specifically, using the
IS_NOT_IN_DB() validation function. The issue arose when calling the
process() method on the form – if the validation failed, then an exception was being thrown:
Now, I don’t know about you, but having an exception which uses the base
Exception type, and simply dumps a (useless)
__repr__() string as the message, isn’t that useful. In fact, I believed that this was how the validation was meant to work – if it failed, this exception would be thrown.
That’s all great, except after testing my form for a while, I noticed a bug where, if the validation failed, the next submission of the form would simply reload the page and not do anything. Uh oh.
After a lot of debugging using the in-browser web2py debugger (I don’t recommend this), I came across the following code, in
I didn’t realise it at first, but this code is actually masking any exceptions thrown lower down in the framework during the validation process!
As all good framework debugging should require, I commented out the
except statement to gain access to the actual exception being thrown, and – lo and behold – the validator was throwing an exception:
The validator was complaining because I had passed it a set of DAL
Row objects, rather than a set of database fields.1 Modifying the call to
IS_NOT_IN_DB() and passing it the correct argument worked straight away, and no new exceptions were thrown.
Maybe the web2py team thought they were helping by masking the exception being thrown2, but I don’t think they were, particularly. If they hadn’t done that, I wouldn’t have spent over an hour trying to fix this problem.