PATCH: SQLAlchemy 0.4 ScopedSession / agnostic SessionContext support

25 views
Skip to first unread message

mike bayer

unread,
Aug 18, 2007, 10:45:26ā€ÆAM8/18/07
to sqle...@googlegroups.com
The attached patch modifies Elixir's "Objectstore" implementation to work for a SessionContext from versions 0.3 and 0.4, as well as the 0.4-only ScopedSession object.Ā  Additionally, a new using_options() option "session" is added, such that any user-defined SessionContext or ScopedSession may be assigned to an Elixir class individually.Ā  So the contextual "Session" which is to be used by Elixir can now be set at three levels; globally using elixir.objectstore, per-module using module.session, or per-class using using_options(session=somesess).

Three tests are added, two of which test using_options(session) against both kinds of session, and a third which tests module-level usage of ScopedSession.

At the very least, the new "Objectstore" class should be implemented which establishes compatibility with ScopedSession which is featured in the Pylons tutorial.

the patch also fixes a bug in versioned.py where an execute() statement could be issued using unicode keywords, which is illegal for the **params calling style.

elixir_sa04.patch

Jonathan LaCour

unread,
Aug 18, 2007, 12:01:55ā€ÆPM8/18/07
to sqle...@googlegroups.com
mike bayer wrote:

> The attached patch modifies Elixir's "Objectstore" implementation to
> work for a SessionContext from versions 0.3 and 0.4, as well as the

> 0.4-onlyScopedSession object. Additionally, a new using_options()


> option "session" is added, such that any user-defined SessionContext
> or ScopedSession may be assigned to an Elixir class individually. So
> the contextual "Session" which is to be used by Elixir can now be set
> at three levels; globally using elixir.objectstore, per-module using
> module.session, or per-class using using_options(session=somesess).
>
> Three tests are added, two of which test using_options(session)
> against both kinds of session, and a third which tests module-level
> usage of ScopedSession.
>
> At the very least, the new "Objectstore" class should be implemented
> which establishes compatibility with ScopedSession which is featured
> in the Pylons tutorial.
>
> the patch also fixes a bug in versioned.py where an execute()
> statement could be issued using unicode keywords, which is illegal for
> the **params calling style.

The patch has been applied, thanks Mike! Its my wife's birthday this
weekend, so my time is all dried up until at least early next week.
This fixes the big nagging problem with 0.4, so I can rest easy now :)

--
Jonathan LaCour
http://cleverdevil.org

Stou Sandalski

unread,
Aug 20, 2007, 4:37:35ā€ÆAM8/20/07
to SQLElixir
Hi,

Ever since I 'upgraded' to the trunk of Elixir today I am getting:

"'EntityDescriptor' object has no attribute 'objectstore'"

when trying to do anything like model.Foo.get_by(id=1). I am using
SQLAlchemy 0.4.0 beta 3, and Pylons 0.9.6

I thought it may be the SAContext I was using, so I removed it, got
the web_setup.py to work again using scoped_session... and then I
received the same message ('EntityDescriptor' object has no attribute
'objectstore') from the controllers.

In model. __init__ I do:

Session = scoped_session(sessionmaker(autoflush=False,
transactional=True, bind=config['pylons.g'].sa_engine))

global session

session = Session()

before declaring any of my database objects...

The weird thing is that the web_setup works... but the unit tests, the
regular web app, and the paster shell are broken... I do nothing
special in my web_setup, just import the module and create / query
objects.

I am sure it's something simple that I am forgetting. Any ideas?

Stou


On Aug 18, 9:01 am, Jonathan LaCour <jonathan-li...@cleverdevil.org>
wrote:

Stou Sandalski

unread,
Aug 20, 2007, 7:18:43ā€ÆAM8/20/07
to SQLElixir
I made it work by putting the following in my model:

Session = scoped_session(sessionmaker(autoflush=False,
transactional=True, bind=config['pylons.g'].sa_engine))

elixir.objectstore = elixir.Objectstore(Session)
elixir.EntityDescriptor.objectstore = elixir.objectstore

which functions fine, except when I try to change/save an object that
uses the 'acts_as_versioned()' extension I get the same error about
the missing objectstore attribute.

Stou

Jian Luo

unread,
Aug 20, 2007, 8:24:34ā€ÆAM8/20/07
to SQLElixir
Same problem here.
I got it resolved by calling elixir.setup_all() in end of model/
__init__.py

Jian

Stou Sandalski

unread,
Aug 21, 2007, 2:03:34ā€ÆAM8/21/07
to SQLElixir
elixir.setup_all() actually didn't work for me, and I am getting
session already attached errors when trying to save versioned objects
(and some others).

Do you mind posting (or emailing me) the relevant model, and
BaseController code that you are using?

Regards,

Stou

Jian Luo

unread,
Aug 21, 2007, 5:32:12ā€ÆAM8/21/07
to SQLElixir
I think it's not because of the model. Maybe, the model.__init__
matters

here is my __init__.py
# --------------------------snip-----------------------------------
from pylons import config
from sqlalchemy import MetaData
from sqlalchemy.orm import scoped_session, sessionmaker

# Global session manager. Session() returns the session object
appropriate for
# the current web request.
Session = scoped_session(
sessionmaker(
autoflush=True, transactional=True,
bind=config['pylons.g'].sa_engine
)
)

import elixir
elixir.objectstore = elixir.Objectstore(Session)
elixir.options_defaults.update({
'shortnames': True,
#'session': Session(),
#'inheritance': 'multi',
})

# Global Metadata
metadata = elixir.metadata
if not metadata.bind:
metadata.bind = config['pylons.g'].sa_engine

del config

# Shortcuts to elixir methods
create_all = elixir.create_all
cleanup_all = elixir.cleanup_all
drop_all = elixir.drop_all
setup_all = elixir.setup_all

from user import User, Group, Permission
from admin import ActionHistory
from localization import *
from meta import *

# preparing orm mapper
setup_all()
# --------------------------snip-----------------------------------


and BaseController:

# --------------------------snip-----------------------------------
class BaseController(WSGIController):
def __call__(self, environ, start_response):
# Refresh database session
#model.resync()
# Add current user to template
c.current_user = get_user()
# Insert any code to be run per request here. The Routes match
# is under environ['pylons.routes_dict'] should you want to
check
# the action or route vars here
try:
return WSGIController.__call__(self, environ,
start_response)
finally:
model.Session.remove()

# --------------------------snip-----------------------------------

Stou Sandalski

unread,
Aug 21, 2007, 6:17:24ā€ÆAM8/21/07
to SQLElixir
Thank you, that actually solved all my problems. I am not really sure
what exactly I was doing different... maybe the lack of global
metadata, but I am never touching this code again. =)

Thank you again,

Stou

Jian Luo

unread,
Aug 21, 2007, 7:59:19ā€ÆAM8/21/07
to SQLElixir
Glad to be helpful

Jian

Jason R. Coombs

unread,
Aug 26, 2007, 1:35:37ā€ÆPM8/26/07
to SQLElixir
Beginning with revision 185 in the trunk (this patch), I'm getting an
error in my application. I find that the video store example
(examples/videostore) is also exhibiting the error.

Here's the traceback:

...
2007-08-26 13:25:53,211 turbogears.visit INFO Visit filter initialised
Unhandled exception in thread started by <bound method Server._start
of <cherryp
y._cpserver.Server object at 0x00D0D9B0>>
Traceback (most recent call last):
File "c:\program files\python\lib\site-packages\cherrypy-2.2.1-
py2.5.egg\cherr
ypy\_cpserver.py", line 78, in _start
Engine._start(self)
File "c:\program files\python\lib\site-packages\cherrypy-2.2.1-
py2.5.egg\cherr
ypy\_cpengine.py", line 108, in _start
func()
File "c:\program files\python\lib\site-packages\TurboGears-1.0.3.2-
py2.5.egg\t
urbogears\startup.py", line 234, in startTurboGears
ext.start_extension()
File "c:\program files\python\lib\site-packages\TurboGears-1.0.3.2-
py2.5.egg\t
urbogears\visit\api.py", line 68, in start_extension
create_extension_model()
File "c:\program files\python\lib\site-packages\TurboGears-1.0.3.2-
py2.5.egg\t
urbogears\visit\api.py", line 87, in create_extension_model
_manager.create_model()
File "c:\program files\python\lib\site-packages\TurboGears-1.0.3.2-
py2.5.egg\t
urbogears\visit\savisit.py", line 38, in create_model
visit_class.mapper.local_table.create(checkfirst=True)
File "build\bdist.win32\egg\elixir\entity.py", line 499, in
__getattribute__
File "build\bdist.win32\egg\elixir\__init__.py", line 142, in
setup_all
File "build\bdist.win32\egg\elixir\entity.py", line 225, in
setup_mapper
File "build\bdist.win32\egg\elixir\entity.py", line 575, in mapper
TypeError: mapper() got an unexpected keyword argument 'properties'

I'm using Turbogears 1.0.3.2 and sqlalchemy 0.3.10 (current stable
releases). If I roll back to elixir revision 184, the problem goes
away.

Let me know if I can do anything more to diagnose the problem.

Regards,
Jason

On Aug 18, 10:45 am, "mike bayer" <zzz...@gmail.com> wrote:
> The attached patch modifies Elixir's "Objectstore" implementation to work
> for a SessionContext from versions 0.3 and 0.4, as well as the

> 0.4-onlyScopedSession object. Additionally, a new using_options()


> option "session"
> is added, such that any user-defined SessionContext or ScopedSession may be
> assigned to an Elixir class individually. So the contextual "Session" which
> is to be used by Elixir can now be set at three levels; globally using
> elixir.objectstore, per-module using module.session, or per-class using
> using_options(session=somesess).
>
> Three tests are added, two of which test using_options(session) against both
> kinds of session, and a third which tests module-level usage of
> ScopedSession.
>
> At the very least, the new "Objectstore" class should be implemented which
> establishes compatibility with ScopedSession which is featured in the Pylons
> tutorial.
>
> the patch also fixes a bug in versioned.py where an execute() statement
> could be issued using unicode keywords, which is illegal for the **params
> calling style.
>

> elixir_sa04.patch
> 12KDownload

Gaetan de Menten

unread,
Aug 27, 2007, 5:12:01ā€ÆAM8/27/07
to sqle...@googlegroups.com
Ok. After some investigation, I remembered Turbogears integration with
Elixir is (or at least was -- I hope this is fixed in TG 1.1 or 2.0)
quite... peculiar. I knew this would just bomb someday. It was just a
matter of when.

The root of the problem is that TurboGears uses ActiveMapper's
objectstore even if you are using Elixir (see turbogears/database.py).
It worked fine until now because ActiveMapper's objectstore had the
same definition as Elixir's. Now Elixir's objectstore changed a little
to be forward compatible with version 0.4 of SQLAlchemy, so it breaks.

Ok, now what can be done about it?
* You could use a patched version of TurboGears. It's probably just a
matter of replacing all occurences of "activemapper" to "elixir" in
turbogears/database.py
* Same as above but using monkeypatch.
* Convince me it should be fixed on Elixir side. This might prove a
tough task unless you show me a clean (ie without an explicit mention
to activemapper) way to do it.

In case it helps, your entities use Turbogears/Activemapper
objectstore because it looks in the module where your entities are
defined and search for a "session" attribute. If one is not found,
it'll use Elixir's defaut sessionwrapper/Objectstore.

So, removing the following line in your model file will fix Elixir's
part of the equation (but will probably break other parts in
Turbogears).
from turbogears.database import session

DISCLAIMER: I've used turbogears for approximately 5min in my life
(but looked at their code more), so there might be another option I'm
not aware of.


--
Gaƫtan de Menten
http://openhex.org

Reply all
Reply to author
Forward
0 new messages