On Sep 10, 2010, at 12:24 PM, Kent Bower wrote:

> I'm wondering if you think my use case is one you would like to support, or 
> if you think it is sort of off on its own (I could tell I wasn't explaining 
> our use case extremely well)...
> 
> Regardless, I am setting the InstrumentedAttribute's implementation's 
> "callable_" so I have control over whether to load related objects on 
> transient/pending objects.
> 
> But the framework doesn't exactly support this in some of its assumptions 
> about the callable_.
> 
> For example, for Collections, it doesn't send "passive=PASSIVE_NO_FETCH" 
> during a set() when it looks for the "old" value:
> 
>         old = self.get(state, dict_)
> 
> whereas, for ScalarObjectAttributeImpl(), the set() method passes 
> passive=PASSIVE_NO_FETCH unless active_history is True.
> 
>     def set(self, state, dict_, value, initiator, passive=PASSIVE_OFF):
>         """Set a value on the given InstanceState.
> 
>         `initiator` is the ``InstrumentedAttribute`` that initiated the
>         ``set()`` operation and is used to control the depth of a circular
>         setter operation.
> 
>         """
>         if initiator is self:
>             return
> 
>         if self.active_history:
>             old = self.get(state, dict_)
>         else:
>             old = self.get(state, dict_, passive=PASSIVE_NO_FETCH)
>              
>         value = self.fire_replace_event(state, dict_, value, old, initiator)
>         dict_[self.key] = value
> 
> 
> Is it appropriate to implement "active_history" on collections and pass 
> passive?
> I can work around this somehow if you don't wish to make that change..., but 
> let me know.

In your implementation of callable_, are you trying to emit change events when 
you set the value ?   the current usage of callable_ is that the values are set 
in the attribute's state without triggering any change event - for collections, 
a method like set_committed_value() is used, which does not look at the "old" 
value - it just puts what you want right there and fires no change events.

The PASSIVE_NO_FETCH in the case of the scalar object impl is an optimization, 
so that when you set a many-to-one attribute, there is no needless SELECT of 
the previous one, in those cases that we've determined don't need to do 
anything to the "old" value.   This optimization doesn't apply to one-to-many 
or many-to-many which is why its not present in the collection version.



> 
> 
> 
> 
> 
> On 9/8/2010 3:34 PM, Kent Bower wrote:
>> 
>> I've got a recipe for what will work well for us.  I imagine it could be 
>> useful for others, although I left out the actual serialization mechanism, 
>> since that will likely be very project specific.  
>> 
>> I'd be happy to put this on the wiki, but if you wanted to look it over 
>> first, you are more than welcome (I'd prefer your feedback).  If you are 
>> busy, I can just post it and hope someone may find it useful.
>> 
>> Thank again for your help,
>> Kent
>> 
>> 
>> On 9/7/2010 7:28 PM, Michael Bayer wrote:
>>> 
>>> 
>>> On Sep 7, 2010, at 6:41 PM, Kent Bower wrote:
>>> 
>>>> Two items:
>>>> 
>>>>  * How does the orm currently determine whether it is safe to try get() 
>>>> (e.i. there are no "funny join conditions")?  If you point me to the 
>>>> function where decision takes place, I can probably answer this myself....
>>> 
>>> it compares the join condition of the relationship() to that of the clause 
>>> which the Mapper uses when it issues get(), then stores that away as a flag 
>>> for future consultation.   It's very unusual for a many-to-one relationship 
>>> to be based on something other than a simple foreign-key->primary key 
>>> relationship, though.
>>> 
>>> 
>>>> 
>>>>  * When I build up the primary key from the foreign key, is there an 
>>>> efficient way to build a composite key in the correct order to pass to 
>>>> get()?  (I thought maybe "synchronize_pairs", but that maybe has to do 
>>>> with getting the direction consistent instead?)  
>>> 
>>> Well if you aren't using any composite primary keys in many-to-ones, you 
>>> wouldn't even have to worry about this.   Otherwise, the two collections to 
>>> correlate would be property.local_remote_pairs and 
>>> property.mapper.primary_key.   Perhaps make a dictionary out of dict([(r, 
>>> l) for l, r in prop.local_remote_pairs]) and your PK value would be 
>>> [getattr(instance, prop.parent.get_property_by_column(mydict[p]).key) for p 
>>> in property.mapper.primary_key].
>>> 
>>> Or if you want to get ambitious you can just copy roughly whats in 
>>> strategies.py on line 605 but then you're digging into internals....and 
>>> looking at that now I'm wondering if strategy._equated_columns is really 
>>> different than local_remote_pairs at all...
>>> 
>>> 
>>> 
>>>> 
>>>> Thanks again, you've been much help!
>>>> 
>>>> 
>>>> 
>>>> On 9/7/2010 5:03 PM, Michael Bayer wrote:
>>>>> 
>>>>> 
>>>>> On Sep 7, 2010, at 4:38 PM, Kent Bower wrote:
>>>>> 
>>>>>> Don't want to strangle me, but when the orm (lazy)loads a MANYTONE 
>>>>>> object, it doesn't go to the database if the object is in the session.  
>>>>>> Can I get "with_parent()" to behave this way, or would I need to 
>>>>>> specifically build up the primary key of the related object and call 
>>>>>> query.get()?
>>>>> 
>>>>> the latter.   You can use get() for all many to ones if you aren't using 
>>>>> any funny join conditions.
>>>>> 
>>>>> 
>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> On 9/7/2010 10:25 AM, Michael Bayer wrote:
>>>>>>> 
>>>>>>> 
>>>>>>> On Sep 7, 2010, at 10:12 AM, Kent Bower wrote:
>>>>>>> 
>>>>>>>> Mike, in your proof of concept, when __getstate__ detected transient, 
>>>>>>>> why did you need to make a copy of self.__dict__? 
>>>>>>>> "self.__dict__.copy()"
>>>>>>> 
>>>>>>> i was modifying the __dict__ from what would be expected in a 
>>>>>>> non-serialized object, so that was to leave the original object being 
>>>>>>> serialized unchanged.
>>>>>>> 
>>>>>>>> 
>>>>>>>> 
>>>>>>>> 
>>>>>>>> On 9/6/2010 2:35 PM, Michael Bayer wrote:
>>>>>>>>> 
>>>>>>>>> On Sep 6, 2010, at 2:11 PM, Kent Bower wrote:
>>>>>>>>> 
>>>>>>>>>> Also, I was hoping you would tell me whether this would be a 
>>>>>>>>>> candidate for subclassing InstrumentedAttribute?  Would that make 
>>>>>>>>>> more sense or providing custom __getstate__ & __setstate__ ?
>>>>>>>>> __getstate__ / __setstate__ are pretty much what I like to use for 
>>>>>>>>> pickle stuff, unless some exotic situation makes me have to use 
>>>>>>>>> __reduce__.   One problem with the recipe is that theres no 
>>>>>>>>> 'deferred' loading of attributes.   So in that sense playing with 
>>>>>>>>> InstrumentedAttribute would give you a chance to put a callable in 
>>>>>>>>> there that does what you want.
>>>>>>>>> 
>>>>>>>>> There is also the possibility that __setstate__ can load up callables 
>>>>>>>>> into the instance_state using state.set_callable().   This is a 
>>>>>>>>> callable that triggers when you access the attribute that is 
>>>>>>>>> otherwise None.   There's a little bit of fanfare required to get 
>>>>>>>>> that callable to assign to the attribute in the right way.   Attached 
>>>>>>>>> is an example of that.   This is all a little more shaky since the 
>>>>>>>>> state/callable API isn't really public.  Hasn't changed for awhile 
>>>>>>>>> but there's no guarantee.
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>>> Thanks for your help, hopefully I'll be able to contribute such a 
>>>>>>>>>> recipe. 
>>>>>>>>>> 
>>>>>>>>>> Kent
>>>>>>>>>> 
>>>>>>>>>> 
>>>>>>>>>> 
>>>>>>>>>>>> Since sqla won't load that for me in the case of transient, I need 
>>>>>>>>>>>> to load the relation manually (unless you feel like enhancing that 
>>>>>>>>>>>> as well). 
>>>>>>>>>>> its not an enhancement - it was a broken behavior that was 
>>>>>>>>>>> specifically removed.   The transient object has no session, so 
>>>>>>>>>>> therefore no SQL can be emitted - there's no context established.  
>>>>>>>>>>> 
>>>>>>>>>>> 
>>>>>>>>>>> 
>>>>>>>>>>>> Now I can manually emulate the obj being persistent with your 
>>>>>>>>>>>> changes for 
>>>>>>>>>>>> 
>>>>>>>>>>>> On Sep 6, 2010, at 10:58 AM, Michael Bayer 
>>>>>>>>>>>> <mike...@zzzcomputing.com> wrote:
>>>>>>>>>>>> 
>>>>>>>>>>>>> On Sep 6, 2010, at 9:06 AM, Kent wrote:
>>>>>>>>>>>>> 
>>>>>>>>>>>>>> with_parent seems to add a join condition.  
>>>>>>>>>>>>> OK, so I guess you read the docs which is why you thought it 
>>>>>>>>>>>>> joined and why you didn't realize it doesn't work for transient.  
>>>>>>>>>>>>> r20b6ce05f194 changes all that so that with_parent() accepts 
>>>>>>>>>>>>> transient objects and will do the "look at the attributes" thing. 
>>>>>>>>>>>>>   The docs are updated as this method does use the lazy loader 
>>>>>>>>>>>>> SQL mechanism, not a join.
>>>>>>>>>>>>> 
>>>>>>>>>>>>> 
>>>>>>>>>>>>> 
>>>>>>>>>>>>>> Is there a way to get at
>>>>>>>>>>>>>> the query object that would be rendered from a lazy load (or what
>>>>>>>>>>>>>> "subqueryload" would render on the subsequent load), but on a
>>>>>>>>>>>>>> transient object, if i supply the session?
>>>>>>>>>>>>>> 
>>>>>>>>>>>>>> even though not "recommended", can it make sqla believe my 
>>>>>>>>>>>>>> transient
>>>>>>>>>>>>>> object is detached by setting its state key?
>>>>>>>>>>>>>> 
>>>>>>>>>>>>>> There are reasons i do not want to add this to the session and
>>>>>>>>>>>>>> disabling autoflush would also cause problems.
>>>>>>>>>>>>>> 
>>>>>>>>>>>>>> 
>>>>>>>>>>>>>> 
>>>>>>>>>>>>>> On Sep 3, 9:58 am, Michael Bayer <mike...@zzzcomputing.com> 
>>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>>> On Sep 3, 2010, at 9:36 AM, Kent wrote:
>>>>>>>>>>>>>>> 
>>>>>>>>>>>>>>>> For the case of customerid = '7', that is a simple problem, 
>>>>>>>>>>>>>>>> but when
>>>>>>>>>>>>>>>> it is a more complex join condition, we only wanted to define 
>>>>>>>>>>>>>>>> this
>>>>>>>>>>>>>>>> condition in one single place in our application (namely, the 
>>>>>>>>>>>>>>>> orm).
>>>>>>>>>>>>>>>> That way, if or when that changes, developers don't need to 
>>>>>>>>>>>>>>>> search for
>>>>>>>>>>>>>>>> other places in the app that needed to manually duplicate the 
>>>>>>>>>>>>>>>> logic of
>>>>>>>>>>>>>>>> the orm join condition.
>>>>>>>>>>>>>>>> If I supplied the DBSession to sqla, it would know how to 
>>>>>>>>>>>>>>>> create the
>>>>>>>>>>>>>>>> proper Query object for this lazyload.  Can you point me in 
>>>>>>>>>>>>>>>> the right
>>>>>>>>>>>>>>>> direction (even if where you point me is not currently part of 
>>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>>> public API)?
>>>>>>>>>>>>>>> Query has the with_parent() method for this use case.  
>>>>>>>>>>>>>>> 
>>>>>>>>>>>>>>> 
>>>>>>>>>>>>>>> 
>>>>>>>>>>>>>>> 
>>>>>>>>>>>>>>> 
>>>>>>>>>>>>>>>> Thanks again,
>>>>>>>>>>>>>>>> Kent
>>>>>>>>>>>>>>>> --
>>>>>>>>>>>>>>>> You received this message because you are subscribed to the 
>>>>>>>>>>>>>>>> Google Groups "sqlalchemy" group.
>>>>>>>>>>>>>>>> To post to this group, send email to 
>>>>>>>>>>>>>>>> sqlalch...@googlegroups.com.
>>>>>>>>>>>>>>>> To unsubscribe from this group, send email to 
>>>>>>>>>>>>>>>> sqlalchemy+unsubscr...@googlegroups.com.
>>>>>>>>>>>>>>>> For more options, visit this group 
>>>>>>>>>>>>>>>> athttp://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 sqlalch...@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 sqlalch...@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 sqlalch...@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 sqlalch...@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 sqlalch...@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 sqlalch...@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 sqlalch...@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 sqlalch...@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 sqlalch...@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 sqlalch...@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 sqlalch...@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 sqlalch...@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 sqlalch...@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