<commit_before># This file is part of Indico.
# Copyright (C) 2002 - 2015 European Organization for Nuclear Research (CERN).
#
# Indico is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 3 of the
# License, or (at your option) any later version.
#
# Indico is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Indico; if not, see <http://www.gnu.org/licenses/>.

from functools import wraps

from indico.core.db import db
from indico.util.decorators import smart_decorator

from MaKaC.common.cache import GenericCache


def iter_acl(acl):
    """Iterates over an ACL in the most efficient order.

    This first yields users, then local groups, and eventually
    multipass groups as a remote group check is much more expensive
    than checking if two users are the same (``==``) or if a user is
    in a local group (SQL query).

    :param acl: any iterable containing users/groups
    """
    return sorted(acl, key=lambda x: (x.is_group, not getattr(x, 'is_local', None)))


def retrieve_principals(iterable, allow_groups=True, legacy=True):
    """Retrieves principal objects from ``(type, info)`` tuples.

    See :func:`retrieve_principal` for details.
    """

    return filter(None, [retrieve_principal(x, allow_groups=allow_groups, legacy=legacy) for x in iterable])


def retrieve_principal(principal, allow_groups=True, legacy=True):
    """Retrieves principal object from a `(type, id)` tuple.

    Valid principal types are 'Avatar', 'User' and 'Group'.

    :param principal: The principal (a tuple/list)
    :param allow_groups: If group principals are allowed
    :param legacy: If legacy wrappers or new objects should be returned.
    """
    from indico.modules.groups import GroupProxy
    from indico.modules.groups.legacy import LocalGroupWrapper, LDAPGroupWrapper
    from indico.modules.users import User

    type_, id_ = principal
    if type_ in {'Avatar', 'User'}:
        user = User.get(int(id_))
        if not user:
            return None
        return user.as_avatar if legacy else user
    elif type_ == 'Group' and allow_groups:
        if isinstance(id_, (int, basestring)):  # legacy group
            group = LocalGroupWrapper(id_) if unicode(id_).isdigit() else LDAPGroupWrapper(id_)
            return group if legacy else group.group
        else:  # new group
            provider, name_or_id = id_
            group = GroupProxy(name_or_id, provider)
            return group.as_legacy_group if legacy else group
    else:
        raise ValueError('Unexpected type: {}'.format(type_))


def principal_from_fossil(fossil, allow_pending=False, allow_groups=True, legacy=True, allow_missing_groups=False):
    """Gets a GroupWrapper or AvatarUserWrapper from a fossil"""
    from indico.modules.groups import GroupProxy
    from indico.modules.users import User

    type_ = fossil['_type']
    id_ = fossil['id']
    if type_ == 'Avatar':
        if isinstance(id_, int) or id_.isdigit():
            # regular user
            user = User.get(int(id_))
        elif allow_pending:
            data = GenericCache('pending_identities').get(id_)
            if not data:
                raise ValueError("Cannot find user '{}' in cache".format(id_))

            data = {k: '' if v is None else v for (k, v) in data.items()}

            # check if there is not already a pending user with that e-mail
            user = User.find_first(email=data['email'], is_pending=True)
            if not user:
                user = User(first_name=data.get('first_name') or '', last_name=data.get('last_name') or '',
                            email=data['email'],
                            address=data.get('address', ''), phone=data.get('phone', ''),
                            affiliation=data.get('affiliation', ''), is_pending=True)
                db.session.add(user)
                db.session.flush()
        else:
            raise ValueError("Id '{}' is not a number and allow_pending=False".format(id_))
        if user is None:
            raise ValueError('User does not exist: {}'.format(id_))
        return user.as_avatar if legacy else user
    elif not allow_groups:
        raise ValueError('Unexpected fossil type: {}'.format(type_))
    elif type_ in {'LocalGroupWrapper', 'LocalGroup'}:
        group = GroupProxy(int(id_))
        if group.group is None:
            raise ValueError('Local group does not exist: {}'.format(id_))
        return group.as_legacy_group if legacy else group
    elif type_ in {'LDAPGroupWrapper', 'MultipassGroup'}:
        provider = fossil['provider']
        group = GroupProxy(id_, provider)
        if group.group is None and not allow_missing_groups:
            raise ValueError('Multipass group does not exist: {}:{}'.format(provider, id_))
        return group.as_legacy_group if legacy else group
    else:
        raise ValueError('Unexpected fossil type: {}'.format(type_))


@smart_decorator
def unify_user_args(fn, legacy=False):
    """Decorator that unifies new/legacy user arguments.

    Any argument of the decorated function that contains either a<commit_msg>Use lowercase email when processing pending users<commit_after># This file is part of Indico.
# Copyright (C) 2002 - 2015 European Organization for Nuclear Research (CERN).
#
# Indico is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 3 of the
# License, or (at your option) any later version.
#
# Indico is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Indico; if not, see <http://www.gnu.org/licenses/>.

from functools import wraps

from indico.core.db import db
from indico.util.decorators import smart_decorator

from MaKaC.common.cache import GenericCache


def iter_acl(acl):
    """Iterates over an ACL in the most efficient order.

    This first yields users, then local groups, and eventually
    multipass groups as a remote group check is much more expensive
    than checking if two users are the same (``==``) or if a user is
    in a local group (SQL query).

    :param acl: any iterable containing users/groups
    """
    return sorted(acl, key=lambda x: (x.is_group, not getattr(x, 'is_local', None)))


def retrieve_principals(iterable, allow_groups=True, legacy=True):
    """Retrieves principal objects from ``(type, info)`` tuples.

    See :func:`retrieve_principal` for details.
    """

    return filter(None, [retrieve_principal(x, allow_groups=allow_groups, legacy=legacy) for x in iterable])


def retrieve_principal(principal, allow_groups=True, legacy=True):
    """Retrieves principal object from a `(type, id)` tuple.

    Valid principal types are 'Avatar', 'User' and 'Group'.

    :param principal: The principal (a tuple/list)
    :param allow_groups: If group principals are allowed
    :param legacy: If legacy wrappers or new objects should be returned.
    """
    from indico.modules.groups import GroupProxy
    from indico.modules.groups.legacy import LocalGroupWrapper, LDAPGroupWrapper
    from indico.modules.users import User

    type_, id_ = principal
    if type_ in {'Avatar', 'User'}:
        user = User.get(int(id_))
        if not user:
            return None
        return user.as_avatar if legacy else user
    elif type_ == 'Group' and allow_groups:
        if isinstance(id_, (int, basestring)):  # legacy group
            group = LocalGroupWrapper(id_) if unicode(id_).isdigit() else LDAPGroupWrapper(id_)
            return group if legacy else group.group
        else:  # new group
            provider, name_or_id = id_
            group = GroupProxy(name_or_id, provider)
            return group.as_legacy_group if legacy else group
    else:
        raise ValueError('Unexpected type: {}'.format(type_))


def principal_from_fossil(fossil, allow_pending=False, allow_groups=True, legacy=True, allow_missing_groups=False):
    """Gets a GroupWrapper or AvatarUserWrapper from a fossil"""
    from indico.modules.groups import GroupProxy
    from indico.modules.users import User

    type_ = fossil['_type']
    id_ = fossil['id']
    if type_ == 'Avatar':
        if isinstance(id_, int) or id_.isdigit():
            # regular user
            user = User.get(int(id_))
        elif allow_pending:
            data = GenericCache('pending_identities').get(id_)
            if not data:
                raise ValueError("Cannot find user '{}' in cache".format(id_))

            data = {k: '' if v is None else v for (k, v) in data.items()}
            email = data['email'].lower()

            # check if there is not already a pending user with that e-mail
            user = User.find_first(email=email, is_pending=True)
            if not user:
                user = User(first_name=data.get('first_name') or '', last_name=data.get('last_name') or '',
                            email=email,
                            address=data.get('address', ''), phone=data.get('phone', ''),
                            affiliation=data.get('affiliation', ''), is_pending=True)
                db.session.add(user)
                db.session.flush()
        else:
            raise ValueError("Id '{}' is not a number and allow_pending=False".format(id_))
        if user is None:
            raise ValueError('User does not exist: {}'.format(id_))
        return user.as_avatar if legacy else user
    elif not allow_groups:
        raise ValueError('Unexpected fossil type: {}'.format(type_))
    elif type_ in {'LocalGroupWrapper', 'LocalGroup'}:
        group = GroupProxy(int(id_))
        if group.group is None:
            raise ValueError('Local group does not exist: {}'.format(id_))
        return group.as_legacy_group if legacy else group
    elif type_ in {'LDAPGroupWrapper', 'MultipassGroup'}:
        provider = fossil['provider']
        group = GroupProxy(id_, provider)
        if group.group is None and not allow_missing_groups:
            raise ValueError('Multipass group does not exist: {}:{}'.format(provider, id_))
        return group.as_legacy_group if legacy else group
    else:
        raise ValueError('Unexpected fossil type: {}'.format(type_))


@smart_decorator
def unify_user_args(fn, legacy=False):
    """Decorator that unifies new/legacy user arguments.

    Any argument of the decorated function that contains either a
{'fraction_non_alphanumeric': 0.09482129832239242, 'fraction_numerical': 0.0016411378555798686, 'mean_word_length': 2.972835929011228, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5068261', 'n_tokens_mistral': 3074, 'n_tokens_neox': 3009, 'n_words': 1101}