def autocommit(func): """ Decorates func such that Django transactions are managed to autocommitt. Django's autocommit decorator begins and commits a transaction on every statement, but will not properly rollback such a failed transaction unless it marked as dirty (something tried to modify the database). This is because Django is optimized for a web request cycle and throws away the connection at the end of each request. """ def _autocommit(*args, **kw): try: transaction.enter_transaction_management() transaction.managed(False) try: result = func(*args, **kw) except: transaction.rollback_unless_managed() raise else: transaction.commit_unless_managed() return result finally: transaction.leave_transaction_management() return wraps(func)(_autocommit)
def json_response(view): def wrapper(request, *args, **kwargs): data = view(request, *args, **kwargs) response = HttpResponse(simplejson.dumps(data, cls = DjangoJSONEncoder)) return response return wraps(view)(wrapper)
def fetch_by_chunks_of(func, items_limit, ids_argument='ids'): """ Class method decorator for fetching ammount of items bigger than allowed at once. Decorator receive parameters: * `items_limit`. Max limit of allowned items to fetch at once * `ids_argument` string, name of argument, that store list of ids. Usage: @fetch_by_chunks_of(1000) def fetch_something(self, ..., *kwargs): .... """ def wrapper(self, *args, **kwargs): if len(args) > 0: raise ValueError("It's prohibited to use non-key arguments for method decorated with @fetch_all, method is %s.%s(), args=%s" % (self.__class__.__name__, func.__name__, args)) ids = kwargs[ids_argument] if ids: kwargs_sliced = dict(kwargs) for chunk in list_chunks_iterator(ids, items_limit): kwargs_sliced[ids_argument] = chunk instances = func(self, **kwargs_sliced) return renew_if_not_equal(self.model, instances, ids) else: return func(self, **kwargs) return wraps(func)(wrapper)
def check_editor_access_permission(view_func): def decorate(request, *args, **kwargs): if not request.user.is_superuser and request.user.has_hue_permission(action="disable_editor_access", app="oozie"): raise PopupException(_('Missing permission to access the Oozie Editor'), error_code=401) return view_func(request, *args, **kwargs) return wraps(view_func)(decorate)
def fetch_only_expired(func, timeout_days, expiration_fieldname='fetched', ids_argument='ids'): """ Class method decorator for fetching only expired items. Add parameter `only_expired=False` for decored method. If `only_expired` is True, method substitute argument `ids_argument` with new value, that consist only expired ids. Decorator receive parameters: * `timeout_days` int, number of day, after that instance is suppose to be expired. * `expiration_fieldname` string, name of datetime field, that indicate time of instance last fetching * `ids_argument` string, name of argument, that store list of ids. Usage: @fetch_only_expired(timeout_days=3) def fetch_something(self, ..., *kwargs): .... """ def wrapper(self, only_expired=False, *args, **kwargs): if len(args) > 0: raise ValueError("It's prohibited to use non-key arguments for method decorated with @fetch_all, method is %s.%s(), args=%s" % (self.__class__.__name__, func.__name__, args)) if only_expired: ids = kwargs[ids_argument] expired_at = datetime.now() - timedelta(timeout_days) ids_non_expired = self.model.objects.filter(**{'%s__gte' % expiration_fieldname: expired_at, 'pk__in': ids}).values_list('pk', flat=True) kwargs[ids_argument] = list(set(ids).difference(set(ids_non_expired))) instances = None if len(kwargs[ids_argument]): instances = func(self, **kwargs) return renew_if_not_equal(self.model, instances, ids) return func(self, **kwargs) return wraps(func)(wrapper)
def _is_enabled(view): def _decorator(request, *args, **kwargs): if setting: return view(request, *args, **kwargs) else: return redirect(next) return wraps(view)(_decorator)
def renderer(func): def wrapper(request, *args, **kw): template_name = False output = func(request, *args, **kw) if isinstance(output, (list, tuple)): template_name = output[1] context = output[0] elif isinstance(output, dict): context = output template_name = template if template_name and context: # manage cookies in dict output cookies = [] if '_cookies' in context: cookies = context.pop('_cookies') response = render_to_response(template_name, context, RequestContext(request)) for cookie in cookies: # https://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpResponse.set_cookie response.set_cookie( key = cookie['key'], value = cookie.get('value'), max_age = cookie.get('max_age'), expires = cookie.get('expires'), path = cookie.get('path', '/'), domain = cookie.get('domain') or getattr(settings, 'SESSION_COOKIE_DOMAIN', None), secure = cookie.get('secure'), httponly = cookie.get('httponly', False) ) return response else: return output return wraps(func)(wrapper)
def inner(view_func): def decorate(request, *args, **kwargs): doc_id = uuid = doc2 = None try: if request.REQUEST.get('workflow'): workflow_id = request.REQUEST.get('workflow') if workflow_id.isdigit(): doc_id = workflow_id else: uuid = workflow_id elif request.GET.get('uuid'): uuid = request.GET.get('uuid') elif request.GET.get('coordinator'): doc_id = request.GET.get('coordinator') elif request.GET.get('bundle'): doc_id = request.GET.get('bundle') elif 'doc_id' in kwargs: doc_id = kwargs['doc_id'] if doc_id is not None: doc2 = Document2.objects.get(id=doc_id) elif uuid is not None: doc2 = Document2.objects.get_by_uuid(user=request.user, uuid=uuid) if doc2: doc2.doc.get().can_read_or_exception(request.user) except Document2.DoesNotExist: raise PopupException(_('Job with %(key)s=%(value)s does not exist') % {'key': 'id' if doc_id else 'uuid', 'value': doc_id or uuid}) return view_func(request, *args, **kwargs) return wraps(view_func)(decorate)
def __call__(ctx, f): """ Here we wrap the view method f and return the wrapped method """ def wrapper(request, *args, **kwargs): """ Wrapper calls the view function, processes the result and returns HttpResponse """ # call the view function itself... context = f(request, *args, **kwargs) # if we happen to have a Response, return it if isinstance(context, HttpResponse): return context # get template from view dict. Can be overridden from the **kwargs template = 'template' in context and context['template'] or None template = kwargs.get('template', template) logger.debug("Rendering template: %s" % template) # allows us to return the dict as json (NB: BlitzGateway objects don't serialize) if template is None or template == 'json': json_data = simplejson.dumps(context) return HttpResponse(json_data, mimetype='application/javascript') else: # allow additional processing of context dict ctx.prepare_context(request, context, *args, **kwargs) t = template_loader.get_template(template) c = RequestContext(request, context) return HttpResponse(t.render(c)) return wraps(f)(wrapper)
def decorator(func): def inner(request): for key in key_list: if key not in request.POST: return HttpResponseForbidden() return func(request) return wraps(func, assigned = available_attrs(func))(inner)
def user_in_project(view): """ Checks if user exists in project and returns 403 if not """ def wrapper(request, *args, **kwargs): try: # if user is a superuser, it has access to all projects if not request.user.is_superuser: #project = request.user.project_set.get(id=kwargs['project_id']) membership = Membership.objects.get(user=request.user, project__id=kwargs['project_id']) roles = Role.objects.all() for role in roles: request.user.groups.remove(role.group) if membership.role.group: request.user.groups.add(membership.role.group) except ObjectDoesNotExist: resp = render_to_response('403.html', context_instance=RequestContext(request)) resp.status_code = 403 return resp return view(request, *args, **kwargs) return wraps(view)(wrapper)
def decorator(func): def inner(request, *args, **kwargs): if request.method not in methods: logger.warning( 'Method Not Allowed (%s): %s' % ( request.method, request.path), extra={ 'status_code': 405, 'request': request } ) return HttpResponseNotAllowed(methods) coerce_put_post(request) language = requested_language(request) if language is not None and language != request.LANGUAGE_CODE: activate_language(language) authorized = check_api_key_authentication(request) if not authorized: authorized = request.user.is_authenticated() if login_required and not authorized: return HttpResponse(status=401) return func(request, *args, **kwargs) return wraps(func, assigned=available_attrs(func))(inner)
def use_locale(func): """ Decorator for tasks with respect to site's current language. e.g.: @task @use_locale def my_task(**kwargs): pass """ def wrapper(*args, **kwargs): try: lang = settings.LANGUAGE_CODE except AttributeError: lang = None language = kwargs.pop('language', lang) prev_language = translation.get_language() if language: translation.activate(language) try: return func(*args, **kwargs) finally: translation.activate(prev_language) wrapper.__doc__ = func.__doc__ wrapper.__name__ = func.__name__ wrapper.__module__ = func.__module__ return wraps(func)(wrapper)
def respects_language(func): ''' Decorator for tasks with respect to site's current language. You can use this decorator in tasks.py together with default @task decorator Be sure that task method have kwargs argument: @task @respects_language def my_task(any_optional_arguments, **kwargs): pass You can call this task this way: from django.utils import translation tasks.my_task.delay(any_optional_arguments, language=translation.get_language()) ''' def wrapper(*args, **kwargs): language = kwargs.pop('language', None) prev_language = translation.get_language() language and translation.activate(language) try: return func(*args, **kwargs) finally: translation.activate(prev_language) wrapper.__doc__ = func.__doc__ wrapper.__name__ = func.__name__ wrapper.__module__ = func.__module__ return wraps(func)(wrapper)
def enforce_lockout(function): """Wraps the provided ``function`` (django.contrib.auth.authenticate) to enforce lockout if the max attempts is exceeded. """ def wrapper(*args, **kwargs): # Get request details from thread local request = getattr(thread_namespace, 'lockoutrequest', None) if request is None: # The call to authenticate must not have come via an HttpRequest, so # lockout is not enforced. return function(*args, **kwargs) params = [] ip = request.META.get('HTTP_X_FORWARDED_FOR', None) if ip: # X_FORWARDED_FOR returns client1, proxy1, proxy2,... ip = ip.split(', ')[0] else: ip = request.META.get('REMOTE_ADDR', '') params.append(ip) if settings.USE_USER_AGENT: useragent = request.META.get('HTTP_USER_AGENT', '') params.append(useragent) if settings.WITH_USERNAME: try: username = kwargs.get('username') or args[0] params.append(username) except IndexError: pass #raise ValueError("No username in parameters, but LOCKOUT_WITH_USERNAME specified") key = generate_base_key(*params) attempts = cache.get(key) or 0 if attempts >= settings.MAX_ATTEMPTS: raise LockedOut() result = function(*args, **kwargs) if result is None: try: attempts = cache.incr(key) except ValueError: # No such key, so set it cache.set(key, 1, settings.ENFORCEMENT_WINDOW) # If attempts is max allowed, set a new key with that # value so that the lockout time will be based on the most # recent login attempt. if attempts >= settings.MAX_ATTEMPTS: cache.set(key, attempts, settings.LOCKOUT_TIME) return result return wraps(function)(wrapper) ########################################################################
def fetch_all(func, max_count): """ Class method decorator for fetching all items. Add parameter `all=False` for decored method. If `all` is True, method runs as many times as it returns any results. Decorator receive 2 parameters: * integer `max_count` - max number of items method able to return Usage: @fetch_all(max_count=200) def fetch_something(self, ..., *kwargs): .... """ def wrapper(self, all=False, return_instances=None, *args, **kwargs): if all: if return_instances is None: return_instances = [] kwargs['count'] = max_count instances = func(self, *args, **kwargs) instances_count = len(instances) return_instances += instances if instances_count > 1: # TODO: make protection somehow from endless loop kwargs['max_id'] = instances[instances_count-1].id return wrapper(self, all=True, return_instances=return_instances, *args, **kwargs) else: return self.model.objects.filter(id__in=[instance.id for instance in return_instances]) else: return func(self, *args, **kwargs) return wraps(func)(wrapper)
def reduce_data_amount(func): """ Class method decorator for handling FacebookGraphAPIError: Please reduce the amount of data you're asking for, then retry your request. Usage: @reduce_data_amount @fetch_all(....) def fetch_something(self, ..., *kwargs): .... """ def wrapper(self, *args, **kwargs): try: instances = func(self, *args, **kwargs) except FacebookError as e: if e.message == "Please reduce the amount of data you're asking for, then retry your request" \ and 'limit' in kwargs: kwargs['limit'] = kwargs['limit'] / 2 log.debug('Reduced amount of asking data in twice. args=%s, kwargs=%s' % (args, kwargs)) return wrapper(self, *args, **kwargs) else: raise return instances return wraps(func)(wrapper)
def decorator(func): def inner(request): if not request.user.is_staff: if 'SID' not in request.POST or not Session.objects.get(pk=request.POST['SID']): return HttpResponseForbidden() return func(request) return wraps(func, assigned=available_attrs(func))(inner)
def commit_on_success(func): """Decorates func such that the current Django transaction is committed on successful return. If func raises an exception, the current transaction is rolled back. Why don't we use django.db.transaction.commit_on_success()? Because it does not commit or rollback unless Django actually tried to change something in the database. It was designed with short-lived web request cycles in mind. This gives us two problems: 1. If the transaction consisted of read-only operations, the connection will stay idle inside a transaction, and that's bad. 2. If a database error occurred inside a transaction, the connection would be useless until the transaction is rolled back. Any further attempts to use the same connection will result in more errors, and a long-lived process will keep spewing error messages. """ def _commit_on_success(*args, **kwargs): try: transaction.enter_transaction_management() transaction.managed(True) try: result = func(*args, **kwargs) except: transaction.rollback() raise else: transaction.commit() return result finally: transaction.leave_transaction_management() return wraps(func)(_commit_on_success)
def inner(view_func): def decorate(request, *args, **kwargs): doc_id = {} try: if request.GET.get('workflow') or request.POST.get('workflow'): workflow_id = request.GET.get('workflow') or request.POST.get('workflow') if workflow_id.isdigit(): doc_id['id'] = workflow_id else: doc_id['uuid'] = workflow_id elif request.GET.get('uuid'): doc_id['uuid'] = request.GET.get('uuid') elif request.GET.get('coordinator'): doc_id['id'] = request.GET.get('coordinator') elif request.GET.get('bundle'): doc_id['id'] = request.GET.get('bundle') elif 'doc_id' in kwargs: doc_id['id'] = kwargs['doc_id'] if doc_id: doc2 = Document2.objects.get(**doc_id) doc2.doc.get().can_read_or_exception(request.user) except Document2.DoesNotExist: raise PopupException(_('Job %(id)s does not exist') % {'id': doc_id}) return view_func(request, *args, **kwargs) return wraps(view_func)(decorate)
def decorator(view_func): def _wrapped_view(self, request, *args, **kwargs): if test_func(request.user): return view_func(self, request, *args, **kwargs) path = urlquote(request.get_full_path()) tup = login_url, redirect_field_name, path return HttpResponseRedirect('%s?%s=%s' % tup) return wraps(view_func)(_wrapped_view)
def get_article_from_id(view): """ Retrieves a specific article, passing it to the view directly """ def wrapper(request, id, *args, **kwargs): article = get_object_or_404(Article, id=int(id)) return view(request, article=article, *args, **kwargs) return wraps(view)(wrapper)
def ensure_company_membership(func): def inner_func(request, *args, **kwargs): user = request.user company = request.company if not user.is_staff and user.id not in company.administrators and user.id not in company.members: raise Http404 return func(request, *args, **kwargs) return wraps(func)(inner_func)
def decorator(func): def inner(request, *args, **kwargs): status = elasticSearchFunctions.check_server_status() if status == 'OK': return func(request, *args, **kwargs) else: return render(request, 'elasticsearch_error.html', {'status': status}) return wraps(func)(inner)
def inner(view_func): def decorate(request, *args, **kwargs): dataset = kwargs.get('dataset') if dataset is not None and not (authorize_get and request.method == 'GET'): Job.objects.can_edit_or_exception(request, dataset.coordinator) return view_func(request, *args, **kwargs) return wraps(view_func)(decorate)
def _decorator(view_func): def _wrapped_view(request, *args, **kwargs): site = AmpCmsSite.objects.get_by_request(request) module_name = kwargs.get(C.URL_KEY_MODULE) page_name = kwargs.get(C.URL_KEY_PAGE) if not site.private: try: module, page = get_public_module_and_page(site, module_name, page_name, request.user) except: # Redirect to the public home page return HttpResponseRedirect(public_url) else: if page is None and (module.redirect_url or module.redirect_module): if module.redirect_url: log.debug('Successfully loaded module. Redirecting to %s' % module.redirect_url) return HttpResponsePermanentRedirect(module.redirect_url) elif module.redirect_module is not None: if request.is_secure(): redirect_url = 'https://%s%s?%s' % (module.redirect_module.site.domain, module.redirect_module.get_absolute_url(), request.GET.urlencode()) else: redirect_url = 'http://%s%s?%s' % (module.redirect_module.site.domain, module.redirect_module.get_absolute_url(), request.GET.urlencode()) log.debug('Successfully loaded module. Redirecting to %s' % redirect_url) return HttpResponsePermanentRedirect(redirect_url) else: log.debug('Successfully loaded module and page: User %s viewing %s and %s' % (request.user.username, module.name, page.name)) if page.private and not request.user.is_authenticated(): log.debug('Site is private and no user is logged in. Redirecting to login.') return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, urlquote(request.get_full_path()))) elif request.user.is_authenticated(): # Attempt to load module and page try: module, page = get_private_module_and_page(site, module_name, page_name, request.user) except PageDoesNotExist: return HttpResponseRedirect(permission_denied_url) except NoPermissions: return HttpResponseRedirect(settings.AMPCMS_ACCOUNT_NO_PERMISSIONS_URL) else: log.debug('Successfully loaded module and page: User %s viewing page %s.%s' % (request.user.username, module.name, page.name)) else: return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, urlquote(request.get_full_path()))) kwargs.update({ C.EXTRA_KWARGS_SITE : site, C.EXTRA_KWARGS_MODULE : module, C.EXTRA_KWARGS_PAGE : page }) if not site.private or request.user.has_acl(module, page): return view_func(request, *args, **kwargs) else: log.warning('User ACL rejected for %s viewing %s.%s' % (request.user, module.name, page.name)) return HttpResponseRedirect(permission_denied_url) return wraps(view_func, assigned=available_attrs(view_func))(_wrapped_view)
def title_check(view): def new_view(request, title, *args, **kwargs): newtitle = title.replace(' ', '_') if newtitle != title: return redirect(request.path.replace(title, newtitle), permanent=True) else: return view(request, title, *args, **kwargs) return wraps(view)(new_view)
def decorator(view_func): def _wrapped_view(request, *args, **kwargs): if test_func(request.user): return view_func(request, *args, **kwargs) path = urlquote(request.get_full_path()) tup = login_url, redirect_field_name, path messages.warning(request, u"You must be logged in to perform this action.") return HttpResponseRedirect('%s?%s=%s' % tup) return wraps(view_func, assigned=available_attrs(view_func))(_wrapped_view)
def decorator(func): def inner(request, *args, **kwargs): if request.POST.has_key(key): return func(request, *args, **kwargs) else: context = context_creator and context_creator(request, *args, **kwargs) \ or RequestContext(request) return render_to_response(template_name, context) return wraps(func)(inner)
def allow_admin_only(view_func): def decorate(request, *args, **kwargs): if not request.user.is_superuser: message = _("Permission denied. You are not an Administrator.") raise PopupException(message) return view_func(request, *args, **kwargs) return wraps(view_func)(decorate)
def opt_generator(func): """ Class method or function decorator makes able to call generator methods as usual methods. Usage: @method_decorator(opt_generator) def some_method(self, ...): ... for count in some_another_method(): yield (count, total) It's possible to call this method 2 different ways: * instance.some_method() - it will return nothing * for count, total in instance.some_method(as_generator=True): print count, total """ def wrapper(*args, **kwargs): as_generator = kwargs.pop('as_generator', False) result = func(*args, **kwargs) return result if as_generator else list(result) return wraps(func)(wrapper)
def decorator(view_func): def _wrapped_view(view, request, *args, **kwargs): obj = None if hasattr(view, 'get_queryset'): pk = kwargs.get('pk') model = view.get_queryset().model if model and pk is not None: obj = get_object_or_404(model, pk=pk) if obj is not None: try: with cache.lock('%s-%s' % (obj.__class__.__name__, obj.pk), timeout=timeout, sleep=sleep, blocking_timeout=blocking_timeout): return view_func(view, request, *args, **kwargs) except LockError: raise Conflict('Resource is locked') else: return view_func(view, request, *args, **kwargs) return wraps(view_func)(_wrapped_view)
def inner(view_func): def decorate(request, *args, **kwargs): doc_id = None job = json.loads(request.POST.get('workflow', '{}')) if not job: job = json.loads(request.POST.get('coordinator', '{}')) elif not job: job = json.loads(request.POST.get('bundle', '{}')) if job and job.get('id'): doc_id = job.get('id') try: doc2 = Document2.objects.get(id=job['id']) doc2.doc.get().can_write_or_exception(request.user) except Document.DoesNotExist: raise PopupException( _('Job %(id)s does not exist') % {'id': doc_id}) return view_func(request, *args, **kwargs) return wraps(view_func)(decorate)
def check_job_access_permission(view_func): """ Decorator ensuring that the user has access to the workflow or coordinator. Arg: 'workflow' or 'coordinator' id. Return: the workflow of coordinator or raise an exception Notice: its gets an id in input and returns the full object in output (not an id). """ def decorate(request, *args, **kwargs): if 'workflow' in kwargs: job_type = 'workflow' else: job_type = 'coordinator' job = kwargs.get(job_type) if job is not None: job = Job.objects.is_accessible_or_exception(request, job) kwargs[job_type] = job return view_func(request, *args, **kwargs) return wraps(view_func)(decorate)
def secure_required(view_func): """ Decorator to switch an url from http to https. If a view is accessed through http and this decorator is applied to that view, than it will return a permanent redirect to the secure (https) version of the same view. The decorator also must check that ``ACCOUNTS_USE_HTTPS`` is enabled. If disabled, it should not redirect to https because the project doesn't support it. """ def _wrapped_view(request, *args, **kwargs): if not request.is_secure(): if accounts_settings.ACCOUNTS_USE_HTTPS: request_url = request.build_absolute_uri( request.get_full_path()) secure_url = request_url.replace('http://', 'https://') return HttpResponsePermanentRedirect(secure_url) return view_func(request, *args, **kwargs) return wraps(view_func, assigned=available_attrs(view_func))(_wrapped_view)
def inner(view_func): def decorate(request, *args, **kwargs): notebook_id = request.GET.get('notebook', request.GET.get('editor')) if not notebook_id: notebook_id = json.loads(request.POST.get('notebook', '{}')).get('id') try: if notebook_id: if str(notebook_id).isdigit(): document = Document2.objects.get(id=notebook_id) document.can_read_or_exception(request.user) else: Document2.objects.get_by_uuid(user=request.user, uuid=notebook_id) except Document2.DoesNotExist: raise PopupException( _('Document %(id)s does not exist') % {'id': notebook_id}) return view_func(request, *args, **kwargs) return wraps(view_func)(decorate)
def edit_project_allowed(func): """ Wraps a view with a signature such as view(request, slug, project_slug=None...) to -> view(request, team, project=None...), authorization credentials for viewing have been checked for the user on that request. """ def wrapper( self, team_slug, project_pk=None, *args, **kwargs): team = get_object_or_404(Team, slug=team_slug) project = None user = kwargs.pop("user") if project_pk is not None: project = get_object_or_404(Project, team=team, pk=project_pk) if not can_edit_project(user, team, project): return raise_forbidden_project(request) kwargs.update({ "user": user, }) return func( team, project, *args, **kwargs) return wraps(func)(wrapper)
def inner(view_func): def decorate(request, *args, **kwargs): doc_id = uuid = doc2 = None try: if request.REQUEST.get('workflow'): workflow_id = request.REQUEST.get('workflow') if workflow_id.isdigit(): doc_id = workflow_id else: uuid = workflow_id elif request.GET.get('uuid'): uuid = request.GET.get('uuid') elif request.GET.get('coordinator'): doc_id = request.GET.get('coordinator') elif request.GET.get('bundle'): doc_id = request.GET.get('bundle') elif 'doc_id' in kwargs: doc_id = kwargs['doc_id'] if doc_id is not None: doc2 = Document2.objects.get(id=doc_id) elif uuid is not None: doc2 = Document2.objects.get_by_uuid(uuid) if doc2: doc2.doc.get().can_read_or_exception(request.user) except Document2.DoesNotExist: raise PopupException( _('Job with %(key)s=%(value)s does not exist') % { 'key': 'id' if doc_id else 'uuid', 'value': doc_id or uuid }) return view_func(request, *args, **kwargs) return wraps(view_func)(decorate)
def check_job_permission(view_func): """ Ensure that the user has access to the job. Assumes that the wrapped function takes a 'jobid' param named 'job'. """ def decorate(request, *args, **kwargs): jobid = kwargs['job'] try: job = get_job(request, job_id=jobid) except ApplicationNotRunning as e: LOG.warn( 'Job %s has not yet been accepted by the RM, will poll for status.' % jobid) return job_not_assigned(request, jobid, request.path) if not SHARE_JOBS.get() and not is_admin(request.user) \ and job.user != request.user.username and not can_view_job(request.user.username, job): raise PopupException( _("You don't have permission to access job %(id)s.") % {'id': jobid}) kwargs['job'] = job return view_func(request, *args, **kwargs) return wraps(view_func)(decorate)
def memoize(func, cache, num_args, offset=0, convert_args_func=None, update_cache_if_empty=True): """ It's like django.utils.functional.memoize but with an extra offset parameter Only the first num_args are considered when creating the key, but starting from offset. """ def wrapper(*args): mem_args = args[offset:num_args] if convert_args_func is not None: mem_args = convert_args_func(mem_args) if mem_args in cache: return cache[mem_args] result = func(*args) if update_cache_if_empty or result: cache[mem_args] = result return result return wraps(func)(wrapper)
def check_privileges(view_func): def decorate(*args, **kwargs): if OPTIMIZER.APPLY_SENTRY_PERMISSIONS.get(): checker = get_checker(user=args[0].user) action = 'SELECT' objects = [] if kwargs.get('db_tables'): for db_table in kwargs['db_tables']: objects.append({ 'server': get_hive_sentry_provider(), 'db': _get_table_name(db_table)['database'], 'table': _get_table_name(db_table)['table'] }) else: objects = [{'server': get_hive_sentry_provider()}] if kwargs.get('database_name'): objects[0]['db'] = kwargs['database_name'] if kwargs.get('table_name'): objects[0]['table'] = kwargs['table_name'] filtered = list(checker.filter_objects(objects, action)) if len(filtered) != len(objects): raise MissingSentryPrivilegeException({ 'pre_filtering': objects, 'post_filtering': filtered, 'diff': len(objects) - len(filtered) }) return view_func(*args, **kwargs) return wraps(view_func)(decorate)
def decorator(view_func): def _wrapped_view(view, request, *args, **kwargs): pk = kwargs.get('pk') obj = None model = view.get_queryset().model if model and pk is not None: obj = get_object_or_404(model, pk=pk) has_permissions = False if accept_global_perms: has_permissions = all( request.user.has_perm(perm) for perm in perms) if not has_permissions: has_permissions = all( request.user.has_perm(perm, obj) for perm in perms) if not has_permissions: raise exceptions.PermissionDenied return view_func(view, request, *args, **kwargs) return wraps(view_func)(_wrapped_view)
def rm_ha(funct): """ Support RM HA by trying other RM API. """ def decorate(api, *args, **kwargs): try: return funct(api, *args, **kwargs) except Exception as ex: ex_message = str(ex) if 'Connection refused' in ex_message or 'Connection aborted' in ex_message or 'standby RM' in ex_message: LOG.info( 'Resource Manager not available, trying another RM: %s.' % ex) rm_ha = get_next_ha_yarncluster(current_user=api.user) if rm_ha is not None: if rm_ha[1].url == api.resource_manager_api.url: raise ex LOG.info('Retrying with Resource Manager: %s.' % rm_ha[1].url) config, api.resource_manager_api = rm_ha return funct(api, *args, **kwargs) raise ex return wraps(funct)(decorate)
def decorator(controller): def wrapper(*args, **kwargs): from tethys_quotas.models import ResourceQuota from tethys_apps.utilities import get_active_app request = None for index, arg in enumerate(args): if isinstance(arg, HttpRequest): request = arg break if request is None: raise ValueError( 'No request given. The app_workspace decorator only works on controllers.' ) try: codename = 'app_workspace_quota' rq = ResourceQuota.objects.get(codename=codename) except ResourceQuota.DoesNotExist: log.warning( 'ResourceQuota with codename {} does not exist.'.format( codename)) # Get the active app app = get_active_app(request, get_class=True) if not passes_quota(app, codename): raise PermissionDenied(rq.help) the_workspace = _get_app_workspace(app) return controller(*args, the_workspace, **kwargs) return wraps(controller)(wrapper)
def fetch_all(func, max_count): """ Class method decorator for fetching all items. Add parameter `all=False` for decored method. If `all` is True, method runs as many times as it returns any results. Decorator receive 2 parameters: * integer `max_count` - max number of items method able to return Usage: @fetch_all(max_count=200) def fetch_something(self, ..., *kwargs): .... """ def wrapper(self, all=False, return_instances=None, *args, **kwargs): if all: if not return_instances: return_instances = [] kwargs['count'] = max_count instances = func(self, *args, **kwargs) instances_count = len(instances) return_instances += instances if instances_count > 1: # TODO: make protection somehow from endless loop kwargs['max_id'] = instances[instances_count - 1].id return wrapper(self, all=True, return_instances=return_instances, *args, **kwargs) else: return self.model.objects.filter( id__in=[instance.id for instance in return_instances]) else: return func(self, *args, **kwargs) return wraps(func)(wrapper)
def pend_form(view): def wrapper(request, form_class, template_name, form_hash=None, *args, **kwargs): if request.method == 'POST': form = form_class(request.POST) if 'pend' in request.POST: form_hash = form.pend() return http.HttpRedirect(form_hash) else: if form.is_valid(): return view(request, form=form, *args, **kwargs) else: if form_hash: form = form_class.resume(form_hash) else: form = form_class() return render_to_response(template_name, {'form': form}, RequestContext(request)) return wraps(view)(wrapper)
except JobExpired, e: raise PopupException( _('Job %s has expired.') % jobid, detail=_('Cannot be found on the History Server.')) except Exception, e: raise PopupException(_('Could not find job %s.') % jobid, detail=e) if not SHARE_JOBS.get() and not request.user.is_superuser \ and job.user != request.user.username and not can_view_job(request.user.username, job): raise PopupException( _("You don't have permission to access job %(id)s.") % {'id': jobid}) kwargs['job'] = job return view_func(request, *args, **kwargs) return wraps(view_func)(decorate) def job_not_assigned(request, jobid, path): if request.GET.get('format') == 'json': result = {'status': -1, 'message': ''} try: get_api(request.user, request.jt).get_job(jobid=jobid) result['status'] = 0 except ApplicationNotRunning, e: result['status'] = 1 except Exception, e: result['message'] = _('Error polling job %s: %s') % (jobid, e) return JsonResponse(result, encoder=JSONEncoderForHTML)
def fetch_all(func, return_all=None, always_all=False, pagination='anchor'): """ Class method decorator for fetching all items. Add parameter `all=False` for decored method. If `all` is True, method runs as many times as it returns any results. Decorator receive parameters: * callback method `return_all`. It's called with the same parameters as decored method after all itmes are fetched. * `always_all` bool - return all instances in any case of argument `all` of decorated method Usage: @fetch_all(return_all=lambda self,instance,*a,**k: instance.items.all()) def fetch_something(self, ..., *kwargs): .... """ def wrapper(self, all=False, instances_all=None, *args, **kwargs): if len(args) > 0: raise ValueError( "It's prohibited to use non-key arguments for method decorated with @fetch_all, method is %s.%s(), args=%s" % (self.__class__.__name__, func.__name__, args)) instances = func(self, **kwargs) if len(instances) == 2 and isinstance(instances, tuple): instances, response = instances if always_all or all: if isinstance(instances, QuerySet): if not instances_all: instances_all = QuerySet().none() instances_count = instances.count() if instances_count: instances_all |= instances elif isinstance(instances, list): if not instances_all: instances_all = [] instances_count = len(instances) instances_all += instances else: raise ValueError( "Wrong type of response from func %s. It should be QuerySet or list, not a %s" % (func, type(instances))) # recursive pagination if instances_count and ( 'has_more' in response and response['has_more'] or 'has_more' not in response and pagination in response): kwargs[pagination] = response.get(pagination) return wrapper(self, all=all, instances_all=instances_all, **kwargs) if return_all: kwargs['instances'] = instances_all return return_all(self, **kwargs) else: return instances_all else: return instances return wraps(func)(wrapper)
def decorator(controller_func): def _wrapped_controller(*args, **kwargs): # With OR check, we assume the permission test passes upfront # Find request (varies position if class method is wrapped) # e.g.: func(request, *args, **kwargs) vs. method(self, request, *args, **kwargs) request_args_index = None the_self = None for index, arg in enumerate(args): if isinstance(arg, HttpRequest): request_args_index = index # Args are everything after the request object if request_args_index is not None: request = args[request_args_index] else: raise ValueError("No HttpRequest object provided.") if request_args_index > 0: the_self = args[0] args = args[request_args_index + 1:] # OR Loop if use_or: pass_permission_test = False for perm in perms: # If any one of the permission evaluates to True, the test passes if has_permission(request, perm): pass_permission_test = True break # AND Loop else: # Assume pass test pass_permission_test = True for perm in perms: # If any one of the permissions evaluates to False, the test fails if not has_permission(request, perm): pass_permission_test = False break if not pass_permission_test: if not raise_exception: # If user is authenticated... if request.user.is_authenticated: # User feedback messages.add_message(request, messages.WARNING, message) # Default redirect URL redirect_url = reverse('app_library') # If there is a referer (i.e.: we followed a link to get here) if 'HTTP_REFERER' in request.META: # Try to redirect to the referer URL referer = request.META['HTTP_REFERER'] parsed_referer = urlparse(referer) # But avoid an infinite redirect loop (if referer is self somehow) if parsed_referer.path != request.path: # e.g. hostname:port request_host_parts = request.get_host().split( ':') # Only attempt redirect if host names are the same if len( request_host_parts ) > 0 and parsed_referer.hostname == request_host_parts[ 0]: redirect_url = parsed_referer.path # Redirect to apps library with message return redirect(redirect_url) # If not authenticated... else: # User feedback messages.add_message( request, messages.INFO, "You must be logged in to access this feature.") # Redirect to login page return redirect( reverse('accounts:login') + '?next=' + request.path) else: # Return Error 404: Not Found in production to prevent directory enumeration if not getattr(settings, 'DEBUG', False): return tethys_portal_error.handler_404(request) return tethys_portal_error.handler_403(request) # Call the controller if the_self is not None: response = controller_func(the_self, request, *args, **kwargs) else: response = controller_func(request, *args, **kwargs) return response return wraps(controller_func)(_wrapped_controller)
def wrap_many_related_descriptor(descriptor_cls): """Wraps the ``descriptor_cls``'s __get__ method to return a modified manager whose all() method will return the cached related objects, if populated. Additionally, add an uncache method to clear the all() cache, and pathes add, remove, and clear to call uncached_all before adding, removing, or clearing. """ if descriptor_cls in (ManyRelatedObjectsDescriptor, ForeignRelatedObjectsDescriptor): def get_attr_name(descriptor): return descriptor.related.get_accessor_name() elif descriptor_cls == ReverseManyRelatedObjectsDescriptor: def get_attr_name(descriptor): return descriptor.field.name else: raise ValueError("invalid descriptor class: %s" % descriptor_cls.__name__) original__get__ = descriptor_cls.__get__ def __get__(self, instance, *args, **kwargs): if instance is None: return original__get__(self, instance, *args, **kwargs) manager = original__get__(self, instance, *args, **kwargs) attr_name = get_attr_name(self) cached_attr_name = "%s%s" % ( cachetree_settings.CACHETREE_MANY_RELATED_PREFIX, attr_name) original_all = manager.__class__.all def all_(*args, **kwargs): try: return getattr(instance, cached_attr_name) except AttributeError: return original_all(*args, **kwargs) manager.__class__.all = wraps(original_all)(all_) def uncache(*args, **kwargs): """Uncaches the manager's all method, if it's cached.""" try: delattr(instance, cached_attr_name) except AttributeError: pass manager.__class__.uncache = uncache # The add, remove, and clear methods should uncache the manager's # all(), since they change the related objects. if hasattr(manager, "add"): original_add = manager.add def add(*args, **kwargs): manager.uncache() return original_add(*args, **kwargs) manager.add = wraps(original_add)(add) if hasattr(manager, "remove"): original_remove = manager.remove def remove(*args, **kwargs): manager.uncache() return original_remove(*args, **kwargs) manager.remove = wraps(original_remove)(remove) if hasattr(manager, "clear"): original_clear = manager.clear def clear(*args, **kwargs): manager.uncache() return original_clear(*args, **kwargs) manager.clear = wraps(original_clear)(clear) return manager descriptor_cls.__get__ = wraps(original__get__)(__get__)
def decorate(api, *args, **kwargs): try: return funct(api, *args, **kwargs) except Exception, ex: if 'Could not connect to' in str(ex): LOG.info('JobTracker not available, trying JT plugin HA: %s.' % ex) jt_ha = get_next_ha_mrcluster() if jt_ha is not None: if jt_ha[1].host == api.jt.host: raise ex config, api.jt = jt_ha return funct(api, *args, **kwargs) raise ex return wraps(funct)(decorate) def rm_ha(funct): """ Support RM HA by trying other RM API. """ def decorate(api, *args, **kwargs): try: return funct(api, *args, **kwargs) except Exception, ex: ex_message = str(ex) if 'Connection refused' in ex_message or 'standby RM' in ex_message: LOG.info( 'Resource Manager not available, trying another RM: %s.' % ex)
def log_errors(function): """Decorator that catches and logs error in the wrapped function. """ def wrapper(*args, **kwargs): try: return function(*args, **kwargs) except Exception, e: logger.error( "Error in {0}.{1}: {2}".format( function.__module__, function.__name__,e), exc_info=e, ) return wraps(function)(wrapper) ######################################################################## def monitor(function): """Decorator that performs monitoring before calling the wrapped function. """ from monitor import ServiceMonitor def wrapper(*args, **kwargs): ServiceMonitor.monitor() return function(*args, **kwargs) return wraps(function)(wrapper) ########################################################################
urlnode = django_url_tag(parser, urltoken) return LocaleURLNode(bits[1], urlnode) class LocaleURLNode(Node): def __init__(self, locale, urlnode): self.locale = locale self.urlnode = urlnode def render(self, context): locale = resolve_variable(self.locale, context) if utils.supported_language(locale) is None: raise ValueError("locale not in settings.LANGUAGES: %s" % locale) path = self.urlnode.render(context) if self.urlnode.asvar: self.urlnode.render(context) context[self.urlnode.asvar] = chlocale(context[self.urlnode.asvar], locale) return '' else: return chlocale(path, locale) def locale_url_wrapper(parser, token): return locale_url(parser, token, django_url_tag=defaulttags.url) locale_url_wrapper = wraps(locale_url)(locale_url_wrapper) register.tag('locale_url', locale_url_wrapper)
def decorator(view): def wrapper(request, *args, **kwargs): response = view(request, *args, **kwargs) response['Content-Type'] = c_type return wraps(view)(wrapper)
class login_required(object): """ OMERO.web specific extension of the Django login_required() decorator, https://docs.djangoproject.com/en/dev/topics/auth/, which is responsible for ensuring a valid L{omero.gateway.BlitzGateway} connection. Is configurable by various options. """ def __init__(self, useragent='OMERO.web', isAdmin=False, isGroupOwner=False, doConnectionCleanup=True, omero_group='-1', allowPublic=None): """ Initialises the decorator. """ self.useragent = useragent self.isAdmin = isAdmin self.isGroupOwner = isGroupOwner self.doConnectionCleanup = doConnectionCleanup self.omero_group = omero_group self.allowPublic = allowPublic def get_login_url(self): """The URL that should be redirected to if not logged in.""" return reverse(settings.LOGIN_VIEW) login_url = property(get_login_url) def get_share_connection(self, request, conn, share_id): try: conn.SERVICE_OPTS.setOmeroShare(share_id) share = conn.getShare(share_id) return conn except: logger.error('Error activating share.', exc_info=True) return None def prepare_share_connection(self, request, conn, share_id): """Prepares the share connection if we have a valid share ID.""" # we always need to clear any dirty 'omero.share' values from previous calls conn.SERVICE_OPTS.setOmeroShare() if share_id is None: return None share = conn.getShare(share_id) try: if share.getOwner().id != conn.getUserId(): return self.get_share_connection(request, conn, share_id) except: logger.error('Error retrieving share connection.', exc_info=True) return None def on_not_logged_in(self, request, url, error=None): """Called whenever the user is not logged in.""" if request.is_ajax(): logger.debug('Request is Ajax, returning HTTP 403.') return HttpResponseForbidden() args = {'url': url} logger.debug('Request is not Ajax, redirecting to %s' % self.login_url) return HttpResponseRedirect('%s?%s' % (self.login_url, urlencode(args))) def on_logged_in(self, request, conn): """ Called whenever the users is successfully logged in. Sets the 'omero.group' option if specified in the constructor """ if self.omero_group is not None: conn.SERVICE_OPTS.setOmeroGroup(self.omero_group) def on_share_connection_prepared(self, request, conn_share): """Called whenever a share connection is successfully prepared.""" pass def verify_is_admin(self, conn): """ If we have been requested to by the isAdmin flag, verify the user is an admin and raise an exception if they are not. """ if self.isAdmin and not conn.isAdmin(): raise Http404 def verify_is_group_owner(self, conn, gid): """ If we have been requested to by the isGroupOwner flag, verify the user is the owner of the provided group. If no group is provided the user's active session group ownership will be verified. """ if not self.isGroupOwner: return if gid is not None: if not conn.isLeader(gid): raise Http404 else: if not conn.isLeader(): raise Http404 def is_valid_public_url(self, server_id, request): """ Verifies that the URL for the resource being requested falls within the scope of the OMERO.webpublic URL filter. """ if settings.PUBLIC_ENABLED: if not hasattr(settings, 'PUBLIC_USER'): logger.warn('OMERO.webpublic enabled but public user ' \ '(omero.web.public.user) not set, disabling ' \ 'OMERO.webpublic.') settings.PUBLIC_ENABLED = False return False if not hasattr(settings, 'PUBLIC_PASSWORD'): logger.warn('OMERO.webpublic enabled but public user ' \ 'password (omero.web.public.password) not set, ' \ 'disabling OMERO.webpublic.') settings.PUBLIC_ENABLED = False return False if self.allowPublic is None: return settings.PUBLIC_URL_FILTER.search( request.path) is not None return self.allowPublic return False def get_public_user_connector(self): """ Returns the current cached OMERO.webpublic connector or None if nothing has been cached. """ if not settings.PUBLIC_CACHE_ENABLED: return return cache.get(settings.PUBLIC_CACHE_KEY) def set_public_user_connector(self, connector): """Sets the current cached OMERO.webpublic connector.""" if not settings.PUBLIC_CACHE_ENABLED \ or connector.omero_session_key is None: return logger.debug('Setting OMERO.webpublic connector: %r' % connector) cache.set(settings.PUBLIC_CACHE_KEY, connector, settings.PUBLIC_CACHE_TIMEOUT) def get_connection(self, server_id, request): """ Prepares a Blitz connection wrapper (from L{omero.gateway}) for use with a view function. """ connection = self.get_authenticated_connection(server_id, request) is_valid_public_url = self.is_valid_public_url(server_id, request) logger.debug('Is valid public URL? %s' % is_valid_public_url) if connection is None and is_valid_public_url: # If OMERO.webpublic is enabled, pick up a username and # password from configuration and use those credentials to # create a connection. logger.debug('OMERO.webpublic enabled, attempting to login ' \ 'with configuration supplied credentials.') if server_id is None: server_id = settings.PUBLIC_SERVER_ID username = settings.PUBLIC_USER password = settings.PUBLIC_PASSWORD is_secure = request.REQUEST.get('ssl', False) logger.debug('Is SSL? %s' % is_secure) # Try and use a cached OMERO.webpublic user session key. public_user_connector = self.get_public_user_connector() if public_user_connector is not None: logger.debug('Attempting to use cached OMERO.webpublic ' \ 'connector: %r' % public_user_connector) connection = public_user_connector.join_connection( self.useragent) if connection is not None: request.session['connector'] = public_user_connector logger.debug('Attempt to use cached OMERO.web public ' \ 'session key successful!') return connection logger.debug('Attempt to use cached OMERO.web public ' \ 'session key failed.') # We don't have a cached OMERO.webpublic user session key, # create a new connection based on the credentials we've been # given. connector = Connector(server_id, is_secure) connection = connector.create_connection(self.useragent, username, password, is_public=True) request.session['connector'] = connector self.set_public_user_connector(connector) elif connection is not None: is_anonymous = connection.isAnonymous() logger.debug('Is anonymous? %s' % is_anonymous) if is_anonymous and not is_valid_public_url: return None return connection def get_authenticated_connection(self, server_id, request): """ Prepares an authenticated Blitz connection wrapper (from L{omero.gateway}) for use with a view function. """ # TODO: Handle previous try_super logic; is it still needed? session = request.session request = request.REQUEST is_secure = request.get('ssl', False) logger.debug('Is SSL? %s' % is_secure) connector = session.get('connector', None) logger.debug('Connector: %s' % connector) if server_id is None: # If no server id is passed, the db entry will not be used and # instead we'll depend on the request.session and request.REQUEST # values if connector is not None: server_id = connector.server_id else: try: server_id = request['server'] except: logger.debug('No Server ID available.') return None # If we have an OMERO session key in our request variables attempt # to make a connection based on those credentials. try: omero_session_key = request['bsession'] connector = Connector(server_id, is_secure) except KeyError: # We do not have an OMERO session key in the current request. pass else: # We have an OMERO session key in the current request use it # to try join an existing connection / OMERO session. logger.debug('Have OMERO session key %s, attempting to join...' % \ omero_session_key) connector.user_id = None connector.omero_session_key = omero_session_key connection = connector.join_connection(self.useragent) session['connector'] = connector return connection # An OMERO session is not available, we're either trying to service # a request to a login page or an anonymous request. username = None password = None try: username = request['username'] password = request['password'] except KeyError: if connector is None: logger.debug('No username or password in request, exiting.') # We do not have an OMERO session or a username and password # in the current request and we do not have a valid connector. # Raise an error (return None). return None if username is not None and password is not None: # We have a username and password in the current request, or # OMERO.webpublic is enabled and has provided us with a username # and password via configureation. Use them to try and create a # new connection / OMERO session. logger.debug('Creating connection with username and password...') connector = Connector(server_id, is_secure) connection = connector.create_connection(self.useragent, username, password) session['connector'] = connector return connection logger.debug('Django session connector: %r' % connector) if connector is not None: # We have a connector, attempt to use it to join an existing # connection / OMERO session. connection = connector.join_connection(self.useragent) if connection is not None: logger.debug('Connector valid, session successfully joined.') return connection # Fall through, we the session we've been asked to join may # be invalid and we may have other credentials as request # variables. logger.debug('Connector is no longer valid, destroying...') del session['connector'] return None session['connector'] = connector return connection def __call__(ctx, f): """ Tries to prepare a logged in connection, then calls function and returns the result. """ def wrapped(request, *args, **kwargs): url = request.REQUEST.get('url') if url is None or len(url) == 0: url = request.get_full_path() doConnectionCleanup = False conn = kwargs.get('conn', None) error = None server_id = kwargs.get('server_id', None) # Short circuit connection retrieval when a connection was # provided to us via 'conn'. This is useful when in testing # mode or when stacking view functions/methods. if conn is None: doConnectionCleanup = ctx.doConnectionCleanup logger.debug('Connection not provided, attempting to get one.') try: conn = ctx.get_connection(server_id, request) except Exception, x: logger.error('Error retrieving connection.', exc_info=True) error = str(x) else: # various configuration & checks only performed on new 'conn' if conn is None: return ctx.on_not_logged_in(request, url, error) else: ctx.on_logged_in(request, conn) ctx.verify_is_admin(conn) ctx.verify_is_group_owner(conn, kwargs.get('gid')) share_id = kwargs.get('share_id') conn_share = ctx.prepare_share_connection( request, conn, share_id) if conn_share is not None: ctx.on_share_connection_prepared(request, conn_share) kwargs['conn'] = conn_share else: kwargs['conn'] = conn #kwargs['error'] = request.REQUEST.get('error') kwargs['url'] = url retval = f(request, *args, **kwargs) try: logger.debug('Doing connection cleanup? %s' % \ doConnectionCleanup) if doConnectionCleanup: if conn is not None and conn.c is not None: for v in conn._proxies.values(): v.close() conn.c.closeSession() except: logger.warn('Failed to clean up connection.', exc_info=True) return retval return wraps(f)(wrapped)
element is a dictionary of kwargs to be passed to the filter function along with the markup to parse. For instance, if MARKITUP_PREVIEW_FILTER is set to:: ('markdown.markdown', {'safe_mode': True}) then calling ``filter_func(text)`` is equivalent to:: from markdown import markdown markdown(text, safe_mode=True) Though the implementation differs, the format of the MARKITUP_PREVIEW_FILTER setting is inspired by James Bennett's django-template-utils_. .. _django-template-utils: http://code.google.com/p/django-template-utils/ """ from django.utils.functional import curry, wraps from markitup.settings import MARKITUP_PREVIEW_FILTER if MARKITUP_PREVIEW_FILTER is None: filter_func = lambda text: text else: filter_path, filter_kwargs = MARKITUP_PREVIEW_FILTER module, funcname = filter_path.rsplit('.', 1) func = getattr(__import__(module, {}, {}, [funcname]), funcname) filter_func = wraps(func)(curry(func, **filter_kwargs))
def fetch_all(func, return_all=None, always_all=False, paging_next_arg_name=None): """ Class method decorator for fetching all items. Add parameter `all=False` for decored method. If `all` is True, method runs as many times as it returns any results. Decorator receive parameters: * callback method `return_all`. It's called with the same parameters as decored method after all itmes are fetched. * `always_all` bool - return all instances in any case of argument `all` of decorated method Usage: @fetch_all(return_all=lambda self,instance,*a,**k: instance.items.all()) def fetch_something(self, ..., *kwargs): .... """ def wrapper(self, *args, **kwargs): all = kwargs.pop('all', False) or always_all instances_all = kwargs.pop('instances_all', None) response = None instances = func(self, *args, **kwargs) if len(instances) == 2 and isinstance(instances, tuple): instances, response = instances if all: if isinstance(instances, QuerySet): if instances_all is None: instances_all = QuerySet().none() instances_all |= instances elif isinstance(instances, list): if instances_all is None: instances_all = [] instances_all += instances else: raise ValueError( "Wrong type of response from func %s. It should be QuerySet or list, not a %s" % (func, type(instances))) # resursive pagination paging_next = paging_cursors = None if response: try: paging_next = response['paging']['next'] except KeyError: pass try: paging_cursors = response['paging']['cursors'] except KeyError: pass if paging_next_arg_name and paging_next and paging_next_arg_name in paging_next \ or paging_next_arg_name and paging_cursors and paging_next_arg_name in paging_cursors: paging_next_arg_value = None # at first look in cursors if paging_cursors: paging_next_arg_value = paging_cursors.get( paging_next_arg_name, None) if paging_next_arg_value is None: # at second look parse from paging_next m = re.findall('%s=([^&]+)' % paging_next_arg_name, paging_next) if len(m): paging_next_arg_value = m[0] # __paging_token=enc_AeylNUQG2Z3DpcZgvUECXW1BHDhsvO8chTp-mQY341mQex3MIce-VnU_PztAiKnskGDcNT61dsycEgphUi9kVy9KYJV2QutwpbPZ0p32OsSQlw m = re.findall('%s=([^&]+)' % '__paging_token', paging_next) if len(m): kwargs['__paging_token'] = m[0] if paging_next_arg_value is None: raise ValueError( "Wrong response pagination value: %s, paging_next_arg_name=%s" % (paging_next, paging_next_arg_name)) # only if argument is changed if kwargs.get(paging_next_arg_name) != paging_next_arg_value: kwargs[paging_next_arg_name] = paging_next_arg_value return wrapper(self, all=all, instances_all=instances_all, *args, **kwargs) if return_all: kwargs['instances'] = instances_all return return_all(self, *args, **kwargs) else: return instances_all else: return instances return wraps(func)(wrapper)
def fetch_all(func, return_all=None, kwargs_offset='offset', kwargs_count='count', default_count=None): """ Class method decorator for fetching all items. Add parameter `all=False` for decored method. If `all` is True, method runs as many times as it returns any results. Decorator receive 2 parameters: * callback method `return_all`. It's called with the same parameters as decored method after all itmes are fetched. * `kwargs_offset` - name of offset parameter among kwargs Usage: @fetch_all(return_all=lambda self,instance,*a,**k: instance.items.all()) def fetch_something(self, ..., *kwargs): .... """ def wrapper(self, all=False, instances_all=None, extra_calls=0, *args, **kwargs): if all: instances = func(self, *args, **kwargs) if isinstance(instances, QuerySet): if not instances_all: instances_all = QuerySet().none() instances_all |= instances instances_count = instances.count() elif isinstance(instances, list): if not instances_all: instances_all = [] instances_all += instances instances_count = len(instances) else: raise ValueError( "Wrong type of response from func %s. It should be QuerySet or list, not a %s" % (func, type(instances))) # print kwargs.get(kwargs_offset, 0), instances_count, extra_calls if instances_count > 0 and (not default_count or instances_count == kwargs.get( kwargs_count, default_count)): # TODO: make protection somehow from endless loop in case # where `kwargs_offset` argument is not make any sense for `func` kwargs[kwargs_offset] = kwargs.get(kwargs_offset, 0) + instances_count return wrapper(self, all=all, instances_all=instances_all, *args, **kwargs) # попытка решить проблему получения репостов поста https://vk.com/wall-36948301_23383?w=shares%2Fwall-36948301_23383 elif extra_calls < 3: kwargs[kwargs_offset] = kwargs.get(kwargs_offset, 0) + 1 extra_calls += 1 return wrapper(self, all=all, instances_all=instances_all, extra_calls=extra_calls, *args, **kwargs) if return_all: return return_all(self, *args, **kwargs) else: return instances_all else: return func(self, *args, **kwargs) return wraps(func)(wrapper)
from django.utils.functional import wraps from chapter4.logging.models import Entry def logged(view): """ Logs any errors that occurred during the view in a special model design for app-specific errors """ def wrapper(request, *args, **kwargs): try: return view(request, *args, **kwargs) except Exception, e: # Log the entry using the application’s Entry model Entry.objects.create(path=request.path, type='View exception', description=str(e)) # Re-raise it so standard error handling still applies raise return wraps(view)(wrapper)
def decorator(controller_func): def _wrapped_controller(request, *args, **kwargs): # With OR check, we assume the permission test passes upfront # Check permission pass_permission_test = True # OR Loop if use_or: pass_permission_test = False for perm in perms: # If any one of the permission evaluates to True, the test passes if has_permission(request, perm): pass_permission_test = True break # AND Loop else: # Assume pass test pass_permission_test = True for perm in perms: # If any one of the permissions evaluates to False, the test fails if not has_permission(request, perm): pass_permission_test = False break if not pass_permission_test: if not raise_exception: # If user is authenticated... if request.user.is_authenticated(): # User feedback messages.add_message(request, messages.WARNING, message) # Default redirect URL redirect_url = reverse('app_library') # If there is a referer (i.e.: we followed a link to get here) if 'HTTP_REFERER' in request.META: # Try to redirect to the referer URL referer = request.META['HTTP_REFERER'] parsed_referer = urlparse(referer) # But avoid an infinite redirect loop (if referer is self somehow) if parsed_referer.path != request.path: # e.g. hostname:port request_host_parts = request.get_host().split( ':') # Only attempt redirect if host names are the same if len( request_host_parts ) > 0 and parsed_referer.hostname == request_host_parts[ 0]: redirect_url = parsed_referer.path # Redirect to apps library with message return redirect(redirect_url) # If not authenticated... else: # User feedback messages.add_message( request, messages.INFO, "You must be logged in to access this feature.") # Redirect to login page return redirect( reverse('accounts:login') + '?next=' + request.path) else: return tethys_portal_error.handler_403(request) return controller_func(request, *args, **kwargs) return wraps(controller_func)(_wrapped_controller)