cubicweb/pyramid/tools.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 29 Sep 2016 23:11:38 +0200
changeset 11760 efb8250e37fb
parent 11701 ca536eec556b
child 11811 f09efeead7f9
permissions -rw-r--r--
Drop deprecated LDAP related script both are relying on the 'entities.source' column which has been dropped in 3.19. They have been written with the old ldapsource in mind, which has been dropped at that time.

"""Various tools.

.. warning::

    This module should be considered as internal implementation details. Use
    with caution, as the API may change without notice.
"""

#: A short-term cache for user clones.
#: used by cached_build_user to speed-up repetitive calls to build_user
#: The expiration is handled in a dumb and brutal way: the whole cache is
#: cleared every 5 minutes.
_user_cache = {}


def clone_user(repo, user):
    """Clone a CWUser instance.

    .. warning::

        The returned clone is detached from any cnx.
        Before using it in any way, it should be attached to a cnx that has not
        this user already loaded.
    """
    CWUser = repo.vreg['etypes'].etype_class('CWUser')
    clone = CWUser(
        None,
        rset=user.cw_rset.copy(),
        row=user.cw_row,
        col=user.cw_col)
    clone.cw_attr_cache = dict(user.cw_attr_cache)
    return clone


def cnx_attach_entity(cnx, entity):
    """Attach an entity to a cnx."""
    entity._cw = cnx
    if entity.cw_rset:
        entity.cw_rset.req = cnx


def cached_build_user(repo, eid):
    """Cached version of
    :meth:`cubicweb.server.repository.Repository._build_user`
    """
    with repo.internal_cnx() as cnx:
        if eid in _user_cache:
            entity = clone_user(repo, _user_cache[eid])
            # XXX the cnx is needed here so that the CWUser instance has an
            # access to the vreg, which it needs when its 'prefered_language'
            # property is accessed.
            # If this property did not need a cnx to access a vreg, we could
            # avoid the internal_cnx() and save more time.
            cnx_attach_entity(cnx, entity)
            return entity

        user = repo._build_user(cnx, eid)
        user.cw_clear_relation_cache()
        _user_cache[eid] = clone_user(repo, user)
        return user


def clear_cache():
    """Clear the user cache"""
    _user_cache.clear()


def includeme(config):
    """Start the cache maintenance loop task.

    Automatically included by :func:`cubicweb.pyramid.make_cubicweb_application`.
    """
    repo = config.registry['cubicweb.repository']
    interval = int(config.registry.settings.get(
        'cubicweb.usercache.expiration_time', 60*5))
    repo.looping_task(interval, clear_cache)