I have a web server running on App Engine that uses ndb
for data storage.
The data model looks something like this:
@acl
class MyModel(ndb.Model):
...
access_control = ndb.JsonProperty(default={})
I use the @acl
decorator to augment my model with some access control methods.
The decorator looks something like this:
def acl(model):
def grant(self, subject, credentials):
logging.debug("ACL before: {}".format(self.access_control))
self.access_control[subject] = { ... } # Set correct value.
logging.debug("ACL after: {}".format(self.access_control))
model.grant = grant
...
...
From my application, then I would expect to call it like this:
>>> mdl = MyModel(...)
>>> mdl.grant("someone", "creds")
ACL before: {}
ACL after: { < properly populated access_control > }
But instead I get something similar to this:
>>> mdl1 = MyModel(...)
>>> mdl1.grant("someone", "creds")
ACL before: {}
ACL after: { < properly populated access_control > }
>>> mdl2 = MyModel(...)
>>> mdl2.grant("someone else", "other creds")
ACL before: { < values from mdl1 > }
ACL after: { < values from mdl1 concatenated with mdl2 > }
This bug is making me suspect that self
in the grant()
function is somehow
acting like a global value, since it's accumulating data from previous calls,
even when these calls are performed on different instances.
The question is: Why are my models spilling data between them?
Is self
in context of the decorator, the same as self
in the context of a class method?