A custom query_cls POC to define in the sessionmaker (i simplify thing by only supporting queries which only request one entity): WrapperQuery : ==> the wrapper checks SA object session before getting an SA object attribute (and if needed we merge it with a new session) ==> merging seems to be costly so i think it must be used with scoped_session ==> awfully unefficient if the object is shared between multiples threads which get attributes on the same object at the same time MemoizeWrapperQuery: ==> the wrapper also memoizes every SA object attributes. ==> it avoid to check session and merge SA object even when getting SA object already loaded attribute ==> we could improve memoize by memoizing SA object already loaded attributes on wrapper __init__
Both are not only usable if used for read actions merging seems to be costly so i think i should class Wrapper(object): > def __init__(self, wrapped): > self._wrapped = wrapped > self._lock = threading.Lock() > > def __getattr__(self, name): > if name == '_sa_instance_state': > return self._wrapped._sa_instance_state > old_session = object_session(self._wrapped) > new_session = api.get_session() > with self._lock: > if old_session is not new_session: > self._wrapped = new_session.merge(self._wrapped) > return getattr(self._wrapped, name) > > class CachedWrapper(object): > def __init__(self, wrapped): > self._wrapped = wrapped > self._lock = threading.Lock() > > def __getattr__(self, name): > if name == '_sa_instance_state': > return self._wrapped._sa_instance_state > old_session = object_session(self._wrapped) > new_session = api.get_session() > with self._lock: > if old_session is not new_session: > self._wrapped = new_session.merge(self._wrapped) > value = getattr(self._wrapped, name) > setattr(self, name, value) > return value > > class XQuery(query.Query): > def __init__(self, wrapper_cls, entities, session=None): > super(XQuery, self).__init__(entities, session=session) > self._wrapper_cls = wrapper_cls > def instances(self, cursor, context): > for cursor in super(XQuery, self).instances(cursor, context): > yield self._wrapper_cls(cursor) > > WrapperQuery = functools.partial(XQuery, Wrapper) > MemoizeWrapperQuery = functools.partial(XQuery, MemoizeWrapper) > Is it the right way ? Will it be more elegant by customizing the declarative_base() ? -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To view this discussion on the web visit https://groups.google.com/d/msg/sqlalchemy/-/-I8SiXWqkk8J. 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.