have you tried 0.8 which now provides HSTORE built in ?

it's not apparent from this code fragment why your flush process is producing 
residual state.  I'd need a fully runnable and succinct test case to analyze 
exactly what's going on.


On Dec 4, 2012, at 4:38 PM, Jason wrote:

> 
> 
> On Tuesday, December 4, 2012 4:15:03 PM UTC-5, Jason wrote:
> Ok I figured out the cause, but not the solution. I am using a mutable type 
> for hstore columns. I have a UserDefinedType for Hstore that just passes 
> everything through to psycopg2's hstore type:
> 
> class HStore(UserDefinedType):
>     """ SQLAlchemy type that passes through values to be handled by a 
> psycopg2 
>         extension type. 
>     """
>     type_name = 'HSTORE'
>     
>     def get_col_spec(self):
>         return self.type_name
>     
>     def bind_processor(self, dialect):
>         return None
>     
>     def result_processor(self, dialect, coltype):
>         return None
>     
>     def is_mutable(self):
>         return True
>     
>     def copy_value(self, value):
>         return copy.copy(value)
> 
> I used the MutationDict from 
> http://docs.sqlalchemy.org/en/rel_0_7/orm/extensions/mutable.html :
> 
> class MutationDict(Mutable, dict):
>     
>     @classmethod
>     def coerce(cls, key, value):
>         "Convert plain dictionaries to MutationDict."
> 
>         if not isinstance(value, MutationDict):
>             if isinstance(value, dict):
>                 return MutationDict(value)
> 
>             # this call will raise ValueError
>             return Mutable.coerce(key, value)
>         else:
>             return value
> 
>     def __setitem__(self, key, value):
>         "Detect dictionary set events and emit change events."
> 
>         dict.__setitem__(self, key, value)
>         self.changed()
> 
>     def __delitem__(self, key):
>         "Detect dictionary del events and emit change events."
> 
>         dict.__delitem__(self, key)
>         self.changed()
> 
> The column definition I use is:
> some_attrs = Column(MutationDict.as_mutable(HStore))
> 
> Then in the actual transaction I am copying one object with that column 
> definition to another object with the same definition:
> 
> newobject.some_attrs = other_object.some_attrs
> 
> If I comment out that line there is only a single flush at the commit time.  
> 
> It looks correct according to the examples I have seen, but if you know why 
> it keeps setting them as dirty please let me know.
> 
> On Tuesday, December 4, 2012 3:16:24 PM UTC-5, Michael Bayer wrote:
> 
> On Dec 4, 2012, at 3:04 PM, Jason wrote:
> 
>> After upgrading to SQLAlchemy 0.7.9 I know receive an error  "FlushError: 
>> Over 100 subsequent flushes have occurred within session.commit() - is an 
>> after_flush() hook creating new objects?" which is was introduced by 
>> http://docs.sqlalchemy.org/en/latest/changelog/changelog_07.html#change-75a53327aac5791fe98ec087706a2821
>>  in the changelog. 
>> 
>> I don't have any after_flush event handlers.  I do have a before_flush event 
>> handler that changes the state of a related object, but that doesn't sound 
>> like what the error is talking about.
>> 
>> How can I debug this further? I am doing this within a Pyramid application, 
>> so I am somewhat removed from the commit logic.
> 
> this error traps the condition that dirty state remains in the Session after 
> a flush has completed.    This is possible if an after_flush hook has added 
> new state, or perhaps also if a mapper.after_update/after_insert etc hook, or 
> even a before_update/before_insert has modified the flush plan, which is not 
> appropriate in any case.
> 
> the best way is to actually create an after_flush() hook with a 
> "pdb.set_trace()" in it; in there, you'd just look at session.new, 
> session.dirty, and session.deleted to ensure that they are empty.
> 
> 
> Looks like copy.copy will call __setitem__ on dict to be copied resulting in 
> it being marked dirty. I had to change the copy code to:
> 
>     def copy_value(self, value):
>         try:
>             # Use dict.copy(), because copy.copy will call __setitem__ on the
>             # value causing it to be marked dirty, which could result in
>             # an infinite loop of flushing dirty copies if an hstore is
>             # copied to another hstore column. 
>             return value.copy()
>         except Exception:
>             return None 
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "sqlalchemy" group.
> To view this discussion on the web visit 
> https://groups.google.com/d/msg/sqlalchemy/-/q7YGmmDyhxsJ.
> To post to this group, send email to sqlalchemy@googlegroups.com.
> To unsubscribe from this group, send email to 
> sqlalchemy+unsubscr...@googlegroups.com.
> For more options, visit this group at 
> http://groups.google.com/group/sqlalchemy?hl=en.

-- 
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 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Reply via email to