yup, so what I can say is that this is one of the many fruits that await you when you get onto 0.7 :). attribute stuff is very difficult to change in a maintenance release as every minute behavior affects all kinds of things.
The history of the attribute system is this: the current idea came online around version 0.4, and in version 0.5 received a major overhaul. The system was built strictly for usage by the unit of work system as an internal system. Around the end of 0.5, or maybe in 0.6, the idea of making first the "events" provided by AttributeExtension public came along, and soon after that the idea of making the history system semi-public so that handy versioning extensions could be built. The theme here is that the attribute history system as a public API is 100% an afterthought and was never its original purpose. The mechanics of the UOW, lazy loading, etc. are all extremely intertwined with the smallest details of how the attribute system works, so it's hard to change. 0.7 made the system a lot stronger (as did 0.6, 0.5, etc.) and it behaves much more nicely, but there's still lots of weird cases where it doesn't. There's proposals in 0.8 to further refine its "public" behavior: see http://www.sqlalchemy.org/trac/ticket/2128 . If you'd like to add suggestions to that, feel free. It's a pretty complicated feature (as we have conditions like: attribute had no value at all, attribute might have had a value but we didn't load it, etc.) On Sep 23, 2011, at 1:27 PM, Kent wrote: > Sorry for not checking in the first place. From the looks of this 0.7 > code and specifically from the comment, it seems you've already > changed this: > > @classmethod > def from_scalar_attribute(cls, attribute, state, current): > original = state.committed_state.get(attribute.key, > _NO_HISTORY) > > if original is _NO_HISTORY: > if current is NO_VALUE: > return cls((), (), ()) > else: > return cls((), [current], ()) > # dont let ClauseElement expressions here trip things up > elif attribute.is_equal(current, original) is True: > return cls((), [current], ()) > else: > # current convention on native scalars is to not > # include information > # about missing previous value in "deleted", but > # we do include None, which helps in some primary > # key situations > if id(original) in _NO_STATE_SYMBOLS: > deleted = () > else: > deleted = [original] > if current is NO_VALUE: > return cls((), (), deleted) > else: > return cls([current], (), deleted) > > > > On Sep 23, 1:12 pm, Michael Bayer <mike...@zzzcomputing.com> wrote: >> I can look later today, but what does 0.7 do? >> >> Sent from my iPhone >> >> On Sep 23, 2011, at 11:17 AM, Kent <jkentbo...@gmail.com> wrote: >> >> >> >> >> >> >> >>> I see the code specifically treats going from None as deleted = (): >>> 1417 else: >>> 1418 -> if original is not None: >>> 1419 deleted = [original] >>> 1420 else: >>> 1421 deleted = () >>> 1422 return cls([current], (), deleted) >> >>> So I guess the question is why and is that inconsistent with going to >>> None? >> >>> On Sep 23, 10:39 am, Kent <jkentbo...@gmail.com> wrote: >>>> I have two scalar columns in this example. (This is SQLAlchemy-0.6.4) >> >>>> ========= To NULL ============== >>>> print l.percentofsale1 >>>> 100 >> >>>> l.percentofsale1=None >> >>>> attributes.get_history(l,'percentofsale1') >>>> ([None], (), [Decimal('100')]) >> >>>> ========= From NULL ============== >>>> print l.discount >>>> None >> >>>> l.discount=Decimal(100) >> >>>> attributes.get_history(l,'discount') >>>> ([Decimal('100')], (), ()) >> >>>> I expected to be able to see the history moving from None to >>>> Decimal('100') like this: >>>> ([Decimal('100')], (), [None]) >> >>>> Which would seem consistent with moving To NULL. Why is the >>>> history.deleted () instead of [None]? >> >>>> Thanks, >>>> Kent >> >>> -- >>> 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 >>> 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 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.