Note that not all object 'fields' are present in the dictionary. For example, 
in our app we may have a SQLAlchemy property '_foo' which is exposed as a 
Python property 'foo'. In this case I believe '_foo' will be in the dictionary, 
but your app should probably be working with 'foo'.

Barry

----- Original Message ----
From: Michael Bayer <[EMAIL PROTECTED]>
To: sqlalchemy@googlegroups.com
Sent: Thursday, May 17, 2007 6:55:31 PM
Subject: [sqlalchemy] Re: Modifying __dict__ doesn't dirty an instance



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)















 
____________________________________________________________________________________
Don't get soaked.  Take a quick peak at the forecast
with the Yahoo! Search weather shortcut.
http://tools.search.yahoo.com/shortcuts/#loc_weather
--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to