On Sep 26, 2011, at 9:13 AM, Kent wrote: > Oh, yes, I had already imagined these types of scenarios, so I > appreciate how the change from () to [None] could break several other > things (which is why I didn't touch it). > We'll certainly move to 0.7, just under much pressure currently to get > functionality in place and I already know 0.7 breaks some of the > things we were using. (We've used 'from sqlalchemy import topological' > for a couple purposes because it nicely sorts dependencies of any > type. I know you were planning to make the metadata immutable... that > would be bad for us as I've written database migration for our project > dependent upon being able to mutate metadata... sqlalchemy works great > for this)
topological is under sqlalchemy.util now, you can do a version neutral import like this: from sqlalchemy import __version__ is_sa_07 = __version__ >= (0, 7) if is_sa_07: from sqlalchemy.util import topological else: from sqlalchemy import topological for the mutate metadata use case, metadata still has "remove()" in 0.7....its no problem at all for SQLA to go down the path of having metadata/Table be fully mutable except that there's a lot of coding/testing/bugs to be dealt with for that...and I'm going pretty slow through just whats up for 0.7.3 and 0.7.4 right now. And really its mainly looking for foreign keys when tables are removed and removing the Table reference from those somehow...or otherwise figuring out how that should work when you remove a Table that is referenced by a ForeignKey (raise an error? that would be easy. but a decision to be made). > > Thanks again, > Kent > > On Sep 23, 10:51 pm, Michael Bayer <mike...@zzzcomputing.com> wrote: >> 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: seehttp://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 >>> 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.