<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def permission_required(perm, queryset=None, login_url=None, raise_exception=False):
 """ Permission check decorator for classbased generic view This decorator works as class decorator DO NOT use ``method_decorator`` or whatever while this decorator will use ``self`` argument for method of classbased generic view. Parameters perm : string A permission string queryset : queryset or model A queryset or model for finding object. With classbased generic view, ``None`` for using view default queryset. When the view does not define ``get_queryset``, ``queryset``, ``get_object``, or ``object`` then ``obj=None`` is used to check permission. With functional generic view, ``None`` for using passed queryset. When non queryset was passed then ``obj=None`` is used to check permission. Examples -------- """

    def wrapper(cls):
        def view_wrapper(view_func):
            @wraps(view_func, assigned=available_attrs(view_func))
            def inner(self, request, *args, **kwargs):
                # get object
                obj = get_object_from_classbased_instance(
                        self, queryset, request, *args, **kwargs
                    )

                if not request.user.has_perm(perm, obj=obj):
                    if raise_exception:
                        raise PermissionDenied
                    else:
                        return redirect_to_login(request, login_url)
                return view_func(self, request, *args, **kwargs)
            return inner
        cls.dispatch = view_wrapper(cls.dispatch)
        return cls
    return wrapper