On Thu, Sep 04, 2008 at 08:59:55PM +0200, Florian Haas wrote:
> class Credential(SQLObject):
> class sqlmeta:
> # necessary for the _set_passwd magic defined below
> cacheValues = False
> username = StringCol(alternateID=True, unique=True)
> passwd = StringCol()
> def _set_passwd(self, value):
> # if the database has a built-in password hashing function,
> # use it. Otherwise, store a SHA256 password hash
> digest = SHA256.new(value).hexdigest()
> So, thanks to Oleg's suggestions, this happily applies PASSWORD() when
> running on MySQL. Beautiful.
> However, on a platform without PASSWORD() (tried sqlite), this happens:
> >>> c = Credential(username="foo", passwd="bar")
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> [rest of stack trace...]
> line 183, in _executeRetry
> raise OperationalError(ErrorMessage(e))
> sqlobject.dberrors.OperationalError: no such function: PASSWORD
> Huh? I said try..except, didn't I? As I said, this makes me feel totally
> braindead. Can someone whack me in the head and point me to the obvious
> thing I am missing?
When the object is being created SQLObject doesn't set attributes one
by one - it collects all name/value pairs and then issues one INSERT query.
I.e., self._SO_set_passwd(func.PASSWORD(value)) doesn't access the SQL
backend and hence doesn't raise an exception; the exception is raised later,
when SQLObject really does INSERT.
See main.py, method _SO_setValue() for details:
self._SO_createValues[name] = dbValue
(I simplified the real code a bit to stress the important points.)
self._SO_set_passwd(func.PASSWORD(value)) will issue an immediate UPDATE
on any subsequent attribute assignment and your try/except will catch it.
So for your magic to work you should create an object without a password
and then update the password:
c = Credential()
c.password = 'password'
Change 'passwd' to StringCol(default=None).
Oleg Broytmann http://phd.pp.ru/ phd@...
Programmers don't die, they just GOSUB without RETURN.