t looks like the first copy of o isn't
refreshed when it's underlying
datastore representation is updated.
Correct: there are two completely independent objects in memory during the execution of function foo
-- both happen to be bound to barenames equal to o
, in different scopes, but that's an irrelevant detail (just further confusing things;-).
o = Odp.get(odpKey)
o.foo = 0
foo()
o = Odp.get(o.key())
assert o.foo == 1 # win
"win" only the first time -- because the o.foo = 0
only affects a copy that's never put to the DB, and then o
is rebound to a third copy just gotten from the DB, then o.foo
will be 1
the first time (if the foo
attribute defaults to 0
) but not on subsequent attempts as it keeps increasing by one every time. You need an o.put()
before the call to foo()
to make the o.foo = 0
assignment have any meaning or sense whatsoever.
A better idea is to have the foo
function accept an optional argument (the object in question) and have it get a fresh copy only if it didn't receive that argument; and then in any case return the object it's working on. IOW, you'd have:
o = Odp.get(odpKey)
o.foo = 0
o = foo(o)
assert o.foo == 1 # always OK
def foo(o=None):
if o is None:
o = Odp.get(odpKey)
o.foo += 1
return o
You might add an o.put()
somewhere, but normally it's better to save only when a set of related changes have all been applied to the in-memory copy. Doing essentially all the work on a single in-memory copy saves a lot of roundtrips to the DB and thereby speeds your app up by a lot.