class CredentialsAlreadyExist(Exception):
class CredentialsNotFound(Exception):
class ModelNotFound(Exception):
class RecordNotFound(Exception): class All(list):
    def matches(self, permissions):
        check = True
        for perm in self:
            if hasattr(perm, 'matches'):
                check &= perm.matches(permissions)
            else:
                check &= perm in permissions
        return check class Any(list):
    def matches(self, permissions):
        check = False
        for perm in self:
            if hasattr(perm, 'matches'):
                check |= perm.matches(permissions)
            else:
                check |= perm in permissions
        return check class DaybedAuthorizationPolicy(object):

    def __init__(self, model_creators="Everyone", token_creators="Everyone",
                 token_managers=None):
        self.model_creators = self._handle_pyramid_constants(model_creators)
        self.token_creators = self._handle_pyramid_constants(token_creators)
        self.token_managers = self._handle_pyramid_constants(token_managers)

    def _handle_pyramid_constants(self, creators):
        if not creators:
            return set()

        creators = set(creators)

        # Handle Pyramid constants.
        if "Authenticated" in creators:
            creators.remove("Authenticated")
            creators.add(Authenticated)

        if "Everyone" in creators:
            creators.remove("Everyone")
            creators.add(Everyone)

        return creators

    def permits(self, context, principals, permission):
        """Returns True or False depending if the token with the specified
        principals has access to the given permission.
        """
        principals = set(principals)
        permissions_required = VIEWS_PERMISSIONS_REQUIRED[permission]
        current_permissions = set()

        if principals.intersection(self.model_creators):
            current_permissions.add("create_model")

        if principals.intersection(self.token_creators):
            current_permissions.add("create_token")

        if principals.intersection(self.token_managers):
            current_permissions.add("manage_token")

        model_id = context.model_id
        if model_id is not None:
            try:
                model_permissions = context.db.get_model_permissions(model_id)
            except backend_exceptions.ModelNotFound:
                model_permissions = {}
                if permission != 'post_model':
                    # Prevent unauthorized error to shadow 404 responses
                    return True
            finally:
                for perm_name, credentials_ids in iteritems(model_permissions):
                    # If one of the principals is in the valid credentials_ids
                    # for this permission, grant the permission.
                    if principals.intersection(credentials_ids):
                        current_permissions.add(perm_name)

        # Remove author's permissions if a record is involved, and if it
        # does not belong to the token.
        record_id = context.record_id
        if record_id is not None:
            try:
                authors = context.db.get_record_authors(model_id, record_id)
            except backend_exceptions.RecordNotFound:
                authors = []
            finally:
                if not principals.intersection(authors):
                    current_permissions -= AUTHORS_PERMISSIONS

        logger.debug("Current permissions: %s", current_permissions)

        # Expose permissions and principals for in_view checks
        context.request.permissions = current_permissions
        context.request.principals = principals

        # Check view permission matches token permissions.
        return permissions_required.matches(current_permissions)

    def principals_allowed_by_permission(self, context, permission):
        raise NotImplementedError()  # PRAGMA NOCOVER def invert_permissions_matrix(permissions_credentials_ids):
    """Reverse from {perm: [credentials_ids]} to {credentials_id: [perms]}."""
    credentials_ids_permissions = defaultdict(set)
    for perm, credentials_ids in iteritems(permissions_credentials_ids):
        for credentials_id in credentials_ids:
            credentials_ids_permissions[credentials_id].add(perm)
    return dict_set2list(credentials_ids_permissions) def dict_set2list(dict_set):
    return dict([(key, sorted(value))
                 for key, value in iteritems(dict_set)]) def dict_list2set(dict_list):
    return dict([(key, set(value))
                 for key, value in iteritems(dict_list)]) def default_model_permissions(credentials_id):
    """ Give all permissions to the model creator.
    Permissions of models created by anonymous (i.e. ``Everyone``)
    cannot be changed.
    """
    permissions = defaultdict(list)
    for perm in PERMISSIONS_SET:
        permissions[perm].append(credentials_id)

    if credentials_id == Everyone:
        permissions.pop('update_permissions')

    return permissions PERMISSIONS_SET = set([
    'read_definition', 'update_permissions',
    'read_permissions', 'update_definition',
    'delete_model',
    'create_record',
    'read_all_records', 'update_all_records', 'delete_all_records',
    'read_own_records', 'update_own_records', 'delete_own_records'
]) def merge_permissions(original, specified):
    """ Merge permissions together, and handle the ``ALL`` shortcut.
    """
    permissions = dict_list2set(original)

    def _add(perm, identifier):
        permissions.setdefault(perm, set()).add(identifier)

    def _discard(perm, identifier):
        permissions.setdefault(perm, set()).discard(identifier)

    for credentials_id, perms in iteritems(specified):
        # Handle remove all
        if '-all' in [perm.lower() for perm in perms]:
            for perm in PERMISSIONS_SET:
                _discard(perm, credentials_id)

        # Handle add all
        elif 'all' in [perm.lstrip('+').lower() for perm in perms]:
            for perm in PERMISSIONS_SET:
                _add(perm, credentials_id)

        # Handle add/remove perms list
        else:
            for perm in [perm.lower() for perm in perms]:
                if perm.startswith('-'):
                    _discard(perm.lstrip('-'), credentials_id)
                else:
                    _add(perm.lstrip('+'), credentials_id)

    return dict_set2list(permissions)
    from unittest2 import TestCase
    from unittest import TestCase  # flake8: noqa
from pyramid.security import Authenticated
from daybed.backends import exceptions
from daybed.permissions import (
    All, Any, DaybedAuthorizationPolicy,
    invert_permissions_matrix, dict_set2list, dict_list2set,
    default_model_permissions, PERMISSIONS_SET, merge_permissions
)
import mock
try:
except ImportError:




class TestAnyAll(TestCase):

    def test_any(self):
        self.assertTrue(Any(['un', 'deux', 'trois'])
            .matches(['un', 'deux']))

        self.assertTrue(Any(['un', 'deux', 'trois'])
            .matches(['un', 'deux', '4']))


        self.assertFalse(Any(['un', 'deux'])