On May 6, 2008, at 12:14 PM, Laurence Rowe wrote:

Martijn Faassen wrote:
One thing I understood from Christian Theune is that with scoped sessions, explicit session.save() is not always necessary. Since I see it being used here, could you perhaps comment on this?

Registering a mapper with Session.mapper would work with this extension, but I'm reluctant to recommend it for two reasons: I don't know how it works with the declarative plugin; and it necessarily limits mapped classes to a single Session and therefor a single engine. In a zope context I think it's quite likely that you could have the same classes mapped to different databases (i.e. two instances of a single application).

hi there -

a little background on the "save_on_init" option of Session.mapper. This behavior has its roots way back in SQLAlchemy 0.1, when there was no Session or Query or anything like that, and objects, when instantiated, went directly to a thread-local registry automatically. When SQLA 0.2 came out, we introduced all the additional constructs like Session and such which are familiar today, but extensions were provided which, when enabled, would re-enable the 0.1 behavior of "everything threadlocal/automatic" in a similar way. Ultimately thats where Session.mapper comes from.

Like all typing-savers, "save on init" by then was used by dozens of Pylons users who swore by it and would scream and yell at any hint of removing this already legacy feature. At the same time, new users who were using Pylons tutorials (and therefore save_on_init, without really knowing it) in conjunction with creating their own Session objects were baffled by error messages like "object X is already in session Y".

By the time 0.4 came out, we had started automating Session a lot more, adding autoflush capability to it. This feature immediately had issues with save_on_init for this reason:

class MyClass(object):
    def __init__(self):
        self.some_variable = session.query(Foobar).filter(xyz).one()

Where above, the query(Foobar) would fire off autoflush, MyClass would be flushed, and then an IntegrityError would be raised since MyClass would be missing some necessary state. Changing "save_on_init" to fire off *after* __init__ was a possibility there but then other things could break.

So I've already not liked save_on_init for a couple of years due to its inherent intrusiveness, and because SA historically does not like being in the business of providing framework features (though we have decided to stay in that arena to some degree with declarative and scoped_session).

The "Session.mapper" feature is stressed a whole lot less in the 0.4 docs, and as I work on the 0.5 docs this week I'm feeling very much like I'm going to remove it from the main documentation altogether. We''re consolidating the "save/update/save_or_update" names into just "add()" and "add_all()", so explicitly adding items to a Session should be a more pleasant experience which I wouldn't want anyone to miss.

The aspect of Session.mapper which is somewhat reduntant vs. declarative is that they both want to add an automatic __init__(**kwargs) method which assigns all given keyword values to the instance. They are not incompatible because Session.mapper only adds an __init__ if none is available already.

The final feature of Session.mapper which is more reasonable is the "query" attribute. This feature allows you to say:


as an equivalent for session.query(MyClass).

For that specific attribute, instead of using Session.mapper, its functionality has been exported into its own descriptor-producing method, like so:

        class MyBaseClass(object):
            query = Session.query_property()

So this is a way to get that one aspect without buying into the Session.mapper thing.

Zope-Dev maillist  -  Zope-Dev@zope.org
**  No cross posts or HTML encoding!  **
(Related lists - http://mail.zope.org/mailman/listinfo/zope-announce
http://mail.zope.org/mailman/listinfo/zope )

Reply via email to