On May 17, 2007, at 5:31 PM, Catherine wrote:
> > I noticed an issue that - well, I honestly don't know whether to call > it a "bug" or not. I need to talk it out with somebody who > understands SQLA better. > > When I retrieve an instance, then alter its attributes by manipulating > its __dict__, the instance doesn't get "dirtied", and the changes > won't be sent to the database when I flush the session. a lot more than that breaks, in fact. > > I can work around the problem pretty easily, like this: > exec(operation, employee.__dict__) > employee._state['modified'] = True > > That change to ._state normally happens in > InstrumentedAttribute.__set__ in sqlalchemy/orm/attributes.py (line > 263), which gets called for "instance.attribute = newvalue", but not > for "instance.__dict__['attribute'] = newvalue". well _state is a private attribute which isnt guaranteed to stay that way in future versions. > > I'm wondering if I should just sit on this workaround personally, or > dig into figuring out how to modify SQLA so it will always work for > __dict__ manipulation. > > So - is direct manipulation of the __dict__ something that SQLA should > support, or would that fall in the realm of "you are getting weird on > us, you're on your own"? I guess that double-underscore sort of > implies "you're on your own", but __dict__ manipulation doesn't seem > overly exotic in practice. the entire method of attribute instrumentation is via property objects added to your classes (in fact they are instances of InstrumentedAttribute). the __dict__ is how to get at the instance attributes while bypassing the attribute instrumentation entirely. while the "_state" hack works right now, and there is an additional way it might work which would be to set the "mutable_scalars" flag to True on all the InstrumentedAttribute objects (thereby ignoring the _state flag), both of those methods still break all the cascade functionality and backref functionality, and will also return the wrong list set of deltas in the case of un-lazyloaded attributes that get set directly via __dict__. i.e. the attributes package is largely event-based and theres no event listening on __dict__ directly. a rewrite would involve replacing the __dict__ of all instances with a custom dictionary that does everything, something i understand is a Python no-no (and also makes the instrumentation that much more opaque, since theres no "bypass" level anymore). the cleanest solution of all is just to replace your call to: myinstance.__dict__ with a proxying dict: class MyDict(dict): def __init__(self, obj): self.obj = obj def __getitem__(self, key): return getattr(self.obj, key) def __setitem__(self, key, value): setattr(self.obj, key, value) def keys(self): return self.obj.__dict__.keys() # etc .. MyDict(myinstance) --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~----------~----~----~----~------~----~------~--~---