text: """
  Provides a set of pluggable permission policies.
  """
  from __future__ import unicode_literals
  
  from django.http import Http404
  
  from rest_framework import exceptions
  from rest_framework.compat import is_authenticated
  
  SAFE_METHODS = ('GET', 'HEAD', 'OPTIONS')
  
  
  class BasePermission(object):
      """
      A base class from which all permission classes should inherit.
      """
  
      def has_permission(self, request, view):
          """
          Return `True` if permission is granted, `False` otherwise.
          """
          return True
  
      def has_object_permission(self, request, view, obj):
          """
          Return `True` if permission is granted, `False` otherwise.
          """
          return True
  
  
  class AllowAny(BasePermission):
      """
      Allow any access.
      This isn't strictly required, since you could use an empty
      permission_classes list, but it's useful because it makes the intention
      more explicit.
      """
  
      def has_permission(self, request, view):
          return True
  
  
  class IsAuthenticated(BasePermission):
      """
      Allows access only to authenticated users.
      """
  
      def has_permission(self, request, view):
          return request.user and is_authenticated(request.user)
  
  
  class IsAdminUser(BasePermission):
      """
      Allows access only to admin users.
      """
  
      def has_permission(self, request, view):
          return request.user and request.user.is_staff
  
  
  class IsAuthenticatedOrReadOnly(BasePermission):
      """
      The request is authenticated as a user, or is a read-only request.
      """
  
      def has_permission(self, request, view):
          return (
              request.method in SAFE_METHODS or
              request.user and
              is_authenticated(request.user)
          )
  
  
  class DjangoModelPermissions(BasePermission):
      """
      The request is authenticated using `django.contrib.auth` permissions.
      See: https://docs.djangoproject.com/en/dev/topics/auth/#permissions
  
      It ensures that the user is authenticated, and has the appropriate
      `add`/`change`/`delete` permissions on the model.
  
      This permission can only be applied against view classes that
      provide a `.queryset` attribute.
      """
  
      # Map methods into required permission codes.
      # Override this if you need to also provide 'view' permissions,
      # or if you want to provide custom permission codes.
      perms_map = {
          'GET': [],
          'OPTIONS': [],
          'HEAD': [],
          'POST': ['%(app_label)s.add_%(model_name)s'],
          'PUT': ['%(app_label)s.change_%(model_name)s'],
          'PATCH': ['%(app_label)s.change_%(model_name)s'],
          'DELETE': ['%(app_label)s.delete_%(model_name)s'],
      }
  
      authenticated_users_only = True
  
      def get_required_permissions(self, method, model_cls):
          """
          Given a model and an HTTP method, return the list of permission
          codes that the user is required to have.
          """
          kwargs = {
              'app_label': model_cls._meta.app_label,
              'model_name': model_cls._meta.model_name
          }
  
          if method not in self.perms_map:
              raise exceptions.MethodNotAllowed(method)
  
          return [perm % kwargs for perm in self.perms_map[method]]
  
      def has_permission(self, request, view):
          # Workaround to ensure DjangoModelPermissions are not applied
          # to the root view when using DefaultRouter.
          if getattr(view, '_ignore_model_permissions', False):
              return True
  
          if hasattr(view, 'get_queryset'):
              queryset = view.get_queryset()
              assert queryset is not None, (
                  '{}.get_queryset() returned None'.format(view.__class__.__name__)
              )
          else:
              queryset = getattr(view, 'queryset', None)
  
          assert queryset is not None, (
              'Cannot apply DjangoModelPermissions on a view that '
              'does not set `.queryset` or have a `.get_queryset()` method.'
          )
  
          perms = self.get_required_permissions(request.method, queryset.model)
  
          return (
              request.user and
              (is_authenticated(request.user) or not self.authenticated_users_only) and
              request.user.has_perms(perms)
          )
  
  
  class DjangoModelPermissionsOrAnonReadOnly(DjangoModelPermissions):
      """
      Similar to DjangoModelPermissions, except that anonymous users are
      allowed read-only access.
      """
      authenticated_users_only = False
  
  
  class DjangoObjectPermissions(DjangoModelPermissions):
      """
      The request is authenticated using Django's object-level permissions.
      It requires an object-permissions-enabled backend, such as Django Guardian.
  
      It ensures that the user is authenticated, and has the appropriate
      `add`/`change`/`delete` permissions on the object using .has_perms.
  
      This permission can only be applied against view classes that
      provide a `.queryset` attribute.
      """
      perms_map = {
          'GET': [],
          'OPTIONS': [],
          'HEAD': [],
          'POST': ['%(app_label)s.add_%(model_name)s'],
          'PUT': ['%(app_label)s.change_%(model_name)s'],
          'PATCH': ['%(app_label)s.change_%(model_name)s'],
          'DELETE': ['%(app_label)s.delete_%(model_name)s'],
      }
  
      def get_required_object_permissions(self, method, model_cls):
          kwargs = {
              'app_label': model_cls._meta.app_label,
              'model_name': model_cls._meta.model_name
          }
  
          if method not in self.perms_map:
              raise exceptions.MethodNotAllowed(method)
  
          return [perm % kwargs for perm in self.perms_map[method]]
  
      def has_object_permission(self, request, view, obj):
          if hasattr(view, 'get_queryset'):
              queryset = view.get_queryset()
          else:
              queryset = getattr(view, 'queryset', None)
  
          assert queryset is not None, (
              'Cannot apply DjangoObjectPermissions on a view that '
              'does not set `.queryset` or have a `.get_queryset()` method.'
          )
  
          model_cls = queryset.model
          user = request.user
  
          perms = self.get_required_object_permissions(request.method, model_cls)
  
          if not user.has_perms(perms, obj):
              # If the user does not have permissions we need to determine if
              # they have read permissions to see 403, or not, and simply see
              # a 404 response.
  
              if request.method in SAFE_METHODS:
                  # Read permissions already checked and failed, no need
                  # to make another lookup.
                  raise Http404
  
              read_perms = self.get_required_object_permissions('GET', model_cls)
              if not user.has_perms(read_perms, obj):
                  raise Http404
  
              # Has read permissions.
              return False
  
          return True
  