<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 function-base generic view This decorator works as function decorator 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(view_func):
        @wraps(view_func, assigned=available_attrs(view_func))
        def inner(request, *args, **kwargs):
            _kwargs = copy.copy(kwargs)
            # overwrite queryset if specified
            if queryset:
                _kwargs['queryset'] = queryset

            # get object from view
            if 'date_field' in _kwargs:
                fn = get_object_from_date_based_view
            else:
                fn = get_object_from_list_detail_view
            if fn.validate(request, *args, **_kwargs):
                obj = fn(request, *args, **_kwargs)
            else:
                # required arguments is not passed
                obj = None

            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(request, *args, **_kwargs)
        return inner
    return wrapper