<commit_before>import logging
from collections import namedtuple
from functools import wraps

from django.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied
from django.shortcuts import get_object_or_404

from .exc import DuplicatePermissionError, NoSuchPermissionError, PermissionsError
from .templatetags.permissions import register


log = logging.getLogger(__name__)


Entry = namedtuple('Entry', ('name', 'perm_func', 'view_decorator', 'model', 'allow_anonymous'))


class PermissionsRegistry:

    """A registry of permissions.

    Create a registry somewhere in your project::

        # my/project/perms.py
        from permissions import PermissionsRegistry

        permissions = PermissionsRegistry()

    Then register permissions for an app like so::

        # my/project/app/perms.py
        from my.project.perms import permissions

        @permissions.register
        def can_do_stuff(user):
            ...

        @permissions.register(model=MyModel)
        def can_do_things(user, instance):
            ...

    TODO: Write more documentation.

    """

    def __init__(self):
        self.__registry = dict()

    def register(self, perm_func=None, model=None, allow_anonymous=False, name=None, replace=False):
        """Register a permission.

        This is typically used as a decorator::

            permissions = PermissionsRegistry()
            @permissions.register
            def can_do_something(user):
                ...

        """
        if perm_func is None:
            return lambda perm_func_: self.register(perm_func_, model, allow_anonymous, name)

        name = name if name is not None else perm_func.__name__
        if name == 'register':
            raise PermissionsError('register cannot be used a permission name')
        elif name in self.__registry and not replace:
            raise DuplicatePermissionError(name)

        view_decorator = self.__make_view_decorator(name, perm_func, model, allow_anonymous)
        self.__registry[name] = Entry(name, perm_func, view_decorator, model, allow_anonymous)

        register.filter(name, perm_func)

        log.debug('Registered permission: {0}'.format(name))
        return perm_func

    __call__ = register

    def __getattr__(self, name):
        try:
            return self.__registry[name].view_decorator
        except KeyError:
            raise NoSuchPermissionError(name)

    def __make_view_decorator(self, perm_name, perm_func, model, allow_anonymous):
        def view_decorator(view=None, field='pk'):

            if view is None:
                return lambda view_: view_decorator(view_, field)
            elif not callable(view):
                raise PermissionsError('Bad call to permissions decorator')
<commit_msg>Add missing arg to recursive register() call<commit_after>import logging
from collections import namedtuple
from functools import wraps

from django.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied
from django.shortcuts import get_object_or_404

from .exc import DuplicatePermissionError, NoSuchPermissionError, PermissionsError
from .templatetags.permissions import register


log = logging.getLogger(__name__)


Entry = namedtuple('Entry', ('name', 'perm_func', 'view_decorator', 'model', 'allow_anonymous'))


class PermissionsRegistry:

    """A registry of permissions.

    Create a registry somewhere in your project::

        # my/project/perms.py
        from permissions import PermissionsRegistry

        permissions = PermissionsRegistry()

    Then register permissions for an app like so::

        # my/project/app/perms.py
        from my.project.perms import permissions

        @permissions.register
        def can_do_stuff(user):
            ...

        @permissions.register(model=MyModel)
        def can_do_things(user, instance):
            ...

    TODO: Write more documentation.

    """

    def __init__(self):
        self.__registry = dict()

    def register(self, perm_func=None, model=None, allow_anonymous=False, name=None, replace=False):
        """Register a permission.

        This is typically used as a decorator::

            permissions = PermissionsRegistry()
            @permissions.register
            def can_do_something(user):
                ...

        """
        if perm_func is None:
            return lambda perm_func_: self.register(perm_func_, model, allow_anonymous, name, replace)

        name = name if name is not None else perm_func.__name__
        if name == 'register':
            raise PermissionsError('register cannot be used a permission name')
        elif name in self.__registry and not replace:
            raise DuplicatePermissionError(name)

        view_decorator = self.__make_view_decorator(name, perm_func, model, allow_anonymous)
        self.__registry[name] = Entry(name, perm_func, view_decorator, model, allow_anonymous)

        register.filter(name, perm_func)

        log.debug('Registered permission: {0}'.format(name))
        return perm_func

    __call__ = register

    def __getattr__(self, name):
        try:
            return self.__registry[name].view_decorator
        except KeyError:
            raise NoSuchPermissionError(name)

    def __make_view_decorator(self, perm_name, perm_func, model, allow_anonymous):
        def view_decorator(view=None, field='pk'):

            if view is None:
                return lambda view_: view_decorator(view_, field)
            elif not callable(view):
                raise PermissionsError('Bad call to permissions decorator')

{'fraction_non_alphanumeric': 0.07958170861396668, 'fraction_numerical': 0.0014179369018078695, 'mean_word_length': 2.828358208955224, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '2323975', 'n_tokens_mistral': 1519, 'n_tokens_neox': 1447, 'n_words': 425}