<commit_before>import logging

from pyramid.security import (
    Allow, Deny,
    Everyone, Authenticated,
    ALL_PERMISSIONS)
from nefertari.acl import SelfParamMixin


from .views import collection_methods, item_methods
from . import registry


log = logging.getLogger(__name__)


actions = {
    'allow': Allow,
    'deny': Deny,
}
special_principals = {
    'everyone': Everyone,
    'authenticated': Authenticated,
}
ALLOW_ALL = (Allow, Everyone, ALL_PERMISSIONS)


def methods_to_perms(perms, methods_map):
    """ Convert permissions (perms) which are either HTTP methods or
    keyword 'all' to a set of valid Pyramid permissions.

    Arguments:
        :perms: List or comma-separated string of HTTP methods, or 'all'
        :methods_map: Map of HTTP methods to permission names (nefertari view
            methods)
    """
    if isinstance(perms, basestring):
        perms = perms.split(',')
    perms = [perm.strip().lower() for perm in perms]
    if 'all' in perms:
        return ALL_PERMISSIONS
    else:
        try:
            return [methods_map[p] for p in perms]
        except KeyError:
            raise ValueError(
                'Unknown method name in permissions: {}. Valid methods: '
                '{}'.format(perms, methods_map.keys()))


def parse_acl(acl_string, methods_map):
    """ Parse raw string :acl_string: of RAML-defined ACLs.

    If :acl_string: is blank or None, all permissions are given.
    Values of ACL action and principal are parsed using `actions` and
    `special_principals` maps and are looked up after `strip()` and `lower()`.

    ACEs in :acl_string: may be separated by newline or semicolon.
    Action, principal and permission list must be separated with space.
    Permissions must be separated with comma.
    E.g. 'allow everyone get,post,patch' and 'deny authenticated delete'

    Arguments:
        :acl_string: Raw RAML string containing defined ACEs.
        :methods_map: Map of HTTP methods to nefertari method handlers' names.
    """
    if not acl_string:
        return [ALLOW_ALL]

    aces_list = acl_string.replace('\n', ';').split(';')
    aces_list = [ace.strip().split(' ', 2) for ace in aces_list if ace]
    aces_list = [(a, b, c.split(',')) for a, b, c in aces_list]
    result_acl = []

    for action_str, princ_str, perms in aces_list:
        # Process action
        action_str = action_str.strip().lower()
        action = actions.get(action_str)
        if action is None:
            raise ValueError('Unknown ACL action: {}. Valid actions: {}'.format(
                action_str, actions.keys()))

        # Process principal
        princ_str = princ_str.strip().lower()
        if princ_str in special_principals:
            principal = special_principals[princ_str]
        elif princ_str.startswith('{{'):
            princ_str = princ_str.strip('{{').strip('}}').strip()
            principal = registry.get(princ_str)
        else:
            principal = 'g:' + princ_str

        # Process permissions
        permissions = methods_to_perms(perms, methods_map)

        result_acl.append((action, principal, permissions))

    return result_acl


class BaseACL(SelfParamMixin):
    """ ACL Base class. """
    __context_class__ = None
    collection_acl = None
    item_acl = None

    def __init__(self, request):
        super(BaseACL, self).__init__()
        self.request = request

    def _apply_callables(self, acl, methods_map, obj=None):
        """ Iterate over ACEs from :acl: and apply callable principals if any.

        Principals are passed 3 arguments on call:
            :ace: Single ACE object that looks like (action, callable,
                permission or [permission])
            :request: Current request object
            :obj: Object for which is being accessed though the ACL
        Principal must return single ACE or a list of ACEs.

        Arguments:
            :acl: Sequence of valid Pyramid ACEs which will be processed
            :methods_map: Map of HTTP methods to nefertari view method names
                (permissions)
            :obj: Object for which is being accessed though the ACL
        """
        new_acl = []
        for i, ace in enumerate(acl):
            principal = ace[1]
            if callable(principal):
                ace = principal(ace=ace, request=self.request, obj=obj)
                if not ace:
                    continue
                ace = [(a, b, methods_to_perms(c, item_methods))
                       for a, b, c in ace]
            if not isinstance(ace[0], (list, tuple)):
                ace = [ace]
            new_acl += ace
        return new_acl

    def __acl__(self):
        """ Apply callables to `self.collection_acl` and return result. """
        return self._apply_callables(
            acl=self.collection_acl,
            methods_map=collection_methods)

    def context_acl(self, obj):
        """ Apply callables to `self.item_acl` and return result. """
        return self._apply_callables(
            acl=self.item_acl,
            methods_map=item_methods,
            obj=obj)

    def __getitem__(self, key):
        """ Get item using method depending on value of `self.es_based` """
        key = self.convert_self_key(key)
        if self.es_based:
            return self.getitem_es(key=key)
        else:
            return self.getitem_db(key=key)

    def getitem_db(self, key):
        """ Get item with ID of :key: from database """
        pk_field = self.__context_class__.pk_field()
        obj = self.__context_class__.get_resource(
            **{pk_field: key})
        obj.__acl__ = self.context_acl(obj)
        obj.__parent__ = self
        obj.__name__ = key
        return obj

    def getitem_es(self, key):
        """ Get item with ID of :key: from elasticsearch """<commit_msg>Rename convert_self_key -> resolve_self_key<commit_after>import logging

from pyramid.security import (
    Allow, Deny,
    Everyone, Authenticated,
    ALL_PERMISSIONS)
from nefertari.acl import SelfParamMixin


from .views import collection_methods, item_methods
from . import registry


log = logging.getLogger(__name__)


actions = {
    'allow': Allow,
    'deny': Deny,
}
special_principals = {
    'everyone': Everyone,
    'authenticated': Authenticated,
}
ALLOW_ALL = (Allow, Everyone, ALL_PERMISSIONS)


def methods_to_perms(perms, methods_map):
    """ Convert permissions (perms) which are either HTTP methods or
    keyword 'all' to a set of valid Pyramid permissions.

    Arguments:
        :perms: List or comma-separated string of HTTP methods, or 'all'
        :methods_map: Map of HTTP methods to permission names (nefertari view
            methods)
    """
    if isinstance(perms, basestring):
        perms = perms.split(',')
    perms = [perm.strip().lower() for perm in perms]
    if 'all' in perms:
        return ALL_PERMISSIONS
    else:
        try:
            return [methods_map[p] for p in perms]
        except KeyError:
            raise ValueError(
                'Unknown method name in permissions: {}. Valid methods: '
                '{}'.format(perms, methods_map.keys()))


def parse_acl(acl_string, methods_map):
    """ Parse raw string :acl_string: of RAML-defined ACLs.

    If :acl_string: is blank or None, all permissions are given.
    Values of ACL action and principal are parsed using `actions` and
    `special_principals` maps and are looked up after `strip()` and `lower()`.

    ACEs in :acl_string: may be separated by newline or semicolon.
    Action, principal and permission list must be separated with space.
    Permissions must be separated with comma.
    E.g. 'allow everyone get,post,patch' and 'deny authenticated delete'

    Arguments:
        :acl_string: Raw RAML string containing defined ACEs.
        :methods_map: Map of HTTP methods to nefertari method handlers' names.
    """
    if not acl_string:
        return [ALLOW_ALL]

    aces_list = acl_string.replace('\n', ';').split(';')
    aces_list = [ace.strip().split(' ', 2) for ace in aces_list if ace]
    aces_list = [(a, b, c.split(',')) for a, b, c in aces_list]
    result_acl = []

    for action_str, princ_str, perms in aces_list:
        # Process action
        action_str = action_str.strip().lower()
        action = actions.get(action_str)
        if action is None:
            raise ValueError('Unknown ACL action: {}. Valid actions: {}'.format(
                action_str, actions.keys()))

        # Process principal
        princ_str = princ_str.strip().lower()
        if princ_str in special_principals:
            principal = special_principals[princ_str]
        elif princ_str.startswith('{{'):
            princ_str = princ_str.strip('{{').strip('}}').strip()
            principal = registry.get(princ_str)
        else:
            principal = 'g:' + princ_str

        # Process permissions
        permissions = methods_to_perms(perms, methods_map)

        result_acl.append((action, principal, permissions))

    return result_acl


class BaseACL(SelfParamMixin):
    """ ACL Base class. """
    __context_class__ = None
    collection_acl = None
    item_acl = None

    def __init__(self, request):
        super(BaseACL, self).__init__()
        self.request = request

    def _apply_callables(self, acl, methods_map, obj=None):
        """ Iterate over ACEs from :acl: and apply callable principals if any.

        Principals are passed 3 arguments on call:
            :ace: Single ACE object that looks like (action, callable,
                permission or [permission])
            :request: Current request object
            :obj: Object for which is being accessed though the ACL
        Principal must return single ACE or a list of ACEs.

        Arguments:
            :acl: Sequence of valid Pyramid ACEs which will be processed
            :methods_map: Map of HTTP methods to nefertari view method names
                (permissions)
            :obj: Object for which is being accessed though the ACL
        """
        new_acl = []
        for i, ace in enumerate(acl):
            principal = ace[1]
            if callable(principal):
                ace = principal(ace=ace, request=self.request, obj=obj)
                if not ace:
                    continue
                ace = [(a, b, methods_to_perms(c, item_methods))
                       for a, b, c in ace]
            if not isinstance(ace[0], (list, tuple)):
                ace = [ace]
            new_acl += ace
        return new_acl

    def __acl__(self):
        """ Apply callables to `self.collection_acl` and return result. """
        return self._apply_callables(
            acl=self.collection_acl,
            methods_map=collection_methods)

    def context_acl(self, obj):
        """ Apply callables to `self.item_acl` and return result. """
        return self._apply_callables(
            acl=self.item_acl,
            methods_map=item_methods,
            obj=obj)

    def __getitem__(self, key):
        """ Get item using method depending on value of `self.es_based` """
        key = self.resolve_self_key(key)
        if self.es_based:
            return self.getitem_es(key=key)
        else:
            return self.getitem_db(key=key)

    def getitem_db(self, key):
        """ Get item with ID of :key: from database """
        pk_field = self.__context_class__.pk_field()
        obj = self.__context_class__.get_resource(
            **{pk_field: key})
        obj.__acl__ = self.context_acl(obj)
        obj.__parent__ = self
        obj.__name__ = key
        return obj

    def getitem_es(self, key):
        """ Get item with ID of :key: from elasticsearch """
{'fraction_non_alphanumeric': 0.0943331621297723, 'fraction_numerical': 0.000684814244136278, 'mean_word_length': 2.3408635973691734, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '5673107', 'n_tokens_mistral': 3457, 'n_tokens_neox': 3288, 'n_words': 1060}