From 0b1a061881ff49b0d56c48e026da421a68318a89 Mon Sep 17 00:00:00 2001 From: Jannis Leidel Date: Sun, 1 May 2011 16:46:02 +0000 Subject: [PATCH] Replaced old-style with new-style decorator syntax. git-svn-id: http://code.djangoproject.com/svn/django/trunk@16138 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- .../contrib/admin/templatetags/admin_list.py | 17 +++--- .../admin/templatetags/admin_modify.py | 6 +- django/contrib/admin/templatetags/log.py | 35 ++++++----- django/contrib/admin/views/decorators.py | 3 +- django/contrib/admindocs/views.py | 18 +++--- .../contrib/comments/templatetags/comments.py | 34 ++++------- django/contrib/contenttypes/generic.py | 3 +- .../flatpages/templatetags/flatpages.py | 3 +- .../contrib/humanize/templatetags/humanize.py | 4 +- .../webdesign/templatetags/webdesign.py | 3 +- django/forms/formsets.py | 3 +- django/forms/models.py | 3 +- django/template/base.py | 4 +- django/template/defaulttags.py | 59 +++++++------------ django/template/loader_tags.py | 7 +-- django/templatetags/cache.py | 3 +- django/templatetags/i18n.py | 22 ++++--- django/utils/decorators.py | 3 +- django/utils/functional.py | 9 ++- django/views/decorators/cache.py | 6 +- django/views/decorators/http.py | 3 +- django/views/decorators/vary.py | 6 +- tests/modeltests/select_for_update/tests.py | 1 - tests/regressiontests/admin_views/views.py | 2 +- 24 files changed, 114 insertions(+), 143 deletions(-) diff --git a/django/contrib/admin/templatetags/admin_list.py b/django/contrib/admin/templatetags/admin_list.py index fdf082be70..5e199cec1d 100644 --- a/django/contrib/admin/templatetags/admin_list.py +++ b/django/contrib/admin/templatetags/admin_list.py @@ -19,6 +19,7 @@ register = Library() DOT = '.' +@register.simple_tag def paginator_number(cl,i): """ Generates an individual page index link in a paginated list. @@ -29,8 +30,8 @@ def paginator_number(cl,i): return mark_safe(u'%d ' % (i+1)) else: return mark_safe(u'%d ' % (escape(cl.get_query_string({PAGE_VAR: i})), (i == cl.paginator.num_pages-1 and ' class="end"' or ''), i+1)) -paginator_number = register.simple_tag(paginator_number) +@register.inclusion_tag('admin/pagination.html') def pagination(cl): """ Generates the series of links to the pages in a paginated list. @@ -75,7 +76,6 @@ def pagination(cl): 'ALL_VAR': ALL_VAR, '1': 1, } -pagination = register.inclusion_tag('admin/pagination.html')(pagination) def result_headers(cl): """ @@ -123,7 +123,8 @@ def result_headers(cl): def _boolean_icon(field_val): BOOLEAN_MAPPING = {True: 'yes', False: 'no', None: 'unknown'} - return mark_safe(u'%s' % (settings.ADMIN_MEDIA_PREFIX, BOOLEAN_MAPPING[field_val], field_val)) + return mark_safe(u'%s' % + (settings.ADMIN_MEDIA_PREFIX, BOOLEAN_MAPPING[field_val], field_val)) def items_for_result(cl, result, form): """ @@ -222,6 +223,7 @@ def result_hidden_fields(cl): if form[cl.model._meta.pk.name].is_hidden: yield mark_safe(force_unicode(form[cl.model._meta.pk.name])) +@register.inclusion_tag("admin/change_list_results.html") def result_list(cl): """ Displays the headers and data list together @@ -230,8 +232,8 @@ def result_list(cl): 'result_hidden_fields': list(result_hidden_fields(cl)), 'result_headers': list(result_headers(cl)), 'results': list(results(cl))} -result_list = register.inclusion_tag("admin/change_list_results.html")(result_list) +@register.inclusion_tag('admin/date_hierarchy.html') def date_hierarchy(cl): """ Displays the date hierarchy for date drill-down functionality. @@ -303,8 +305,8 @@ def date_hierarchy(cl): 'title': str(year.year), } for year in years] } -date_hierarchy = register.inclusion_tag('admin/date_hierarchy.html')(date_hierarchy) +@register.inclusion_tag('admin/search_form.html') def search_form(cl): """ Displays a search form for searching the list. @@ -314,12 +316,12 @@ def search_form(cl): 'show_result_count': cl.result_count != cl.full_result_count, 'search_var': SEARCH_VAR } -search_form = register.inclusion_tag('admin/search_form.html')(search_form) +@register.inclusion_tag('admin/filter.html') def admin_list_filter(cl, spec): return {'title': spec.title(), 'choices' : list(spec.choices(cl))} -admin_list_filter = register.inclusion_tag('admin/filter.html')(admin_list_filter) +@register.inclusion_tag('admin/actions.html', takes_context=True) def admin_actions(context): """ Track the number of times the action field has been rendered on the page, @@ -327,4 +329,3 @@ def admin_actions(context): """ context['action_index'] = context.get('action_index', -1) + 1 return context -admin_actions = register.inclusion_tag("admin/actions.html", takes_context=True)(admin_actions) diff --git a/django/contrib/admin/templatetags/admin_modify.py b/django/contrib/admin/templatetags/admin_modify.py index 8e6f0ab5ce..e55b3bf2bd 100644 --- a/django/contrib/admin/templatetags/admin_modify.py +++ b/django/contrib/admin/templatetags/admin_modify.py @@ -2,6 +2,7 @@ from django import template register = template.Library() +@register.inclusion_tag('admin/prepopulated_fields_js.html', takes_context=True) def prepopulated_fields_js(context): """ Creates a list of prepopulated_fields that should render Javascript for @@ -17,8 +18,8 @@ def prepopulated_fields_js(context): prepopulated_fields.extend(inline_admin_form.prepopulated_fields) context.update({'prepopulated_fields': prepopulated_fields}) return context -prepopulated_fields_js = register.inclusion_tag('admin/prepopulated_fields_js.html', takes_context=True)(prepopulated_fields_js) +@register.inclusion_tag('admin/submit_line.html', takes_context=True) def submit_row(context): """ Displays the row of buttons for delete and save. @@ -39,8 +40,8 @@ def submit_row(context): 'is_popup': is_popup, 'show_save': True } -submit_row = register.inclusion_tag('admin/submit_line.html', takes_context=True)(submit_row) +@register.filter def cell_count(inline_admin_form): """Returns the number of cells used in a tabular inline""" count = 1 # Hidden cell with hidden 'id' field @@ -53,4 +54,3 @@ def cell_count(inline_admin_form): # Delete checkbox count += 1 return count -cell_count = register.filter(cell_count) diff --git a/django/contrib/admin/templatetags/log.py b/django/contrib/admin/templatetags/log.py index 663830b36e..888b5ed9c3 100644 --- a/django/contrib/admin/templatetags/log.py +++ b/django/contrib/admin/templatetags/log.py @@ -20,7 +20,8 @@ class AdminLogNode(template.Node): context[self.varname] = LogEntry.objects.filter(user__id__exact=user_id).select_related('content_type', 'user')[:self.limit] return '' -class DoGetAdminLog: +@register.tag +def get_admin_log(parser, token): """ Populates a template variable with the admin log for the given criteria. @@ -38,20 +39,18 @@ class DoGetAdminLog: (user ID) or the name of a template context variable containing the user object whose ID you want. """ - def __init__(self, tag_name): - self.tag_name = tag_name - - def __call__(self, parser, token): - tokens = token.contents.split() - if len(tokens) < 4: - raise template.TemplateSyntaxError("'%s' statements require two arguments" % self.tag_name) - if not tokens[1].isdigit(): - raise template.TemplateSyntaxError("First argument in '%s' must be an integer" % self.tag_name) - if tokens[2] != 'as': - raise template.TemplateSyntaxError("Second argument in '%s' must be 'as'" % self.tag_name) - if len(tokens) > 4: - if tokens[4] != 'for_user': - raise template.TemplateSyntaxError("Fourth argument in '%s' must be 'for_user'" % self.tag_name) - return AdminLogNode(limit=tokens[1], varname=tokens[3], user=(len(tokens) > 5 and tokens[5] or None)) - -register.tag('get_admin_log', DoGetAdminLog('get_admin_log')) + tokens = token.contents.split() + if len(tokens) < 4: + raise template.TemplateSyntaxError( + "'get_admin_log' statements require two arguments") + if not tokens[1].isdigit(): + raise template.TemplateSyntaxError( + "First argument to 'get_admin_log' must be an integer") + if tokens[2] != 'as': + raise template.TemplateSyntaxError( + "Second argument to 'get_admin_log' must be 'as'") + if len(tokens) > 4: + if tokens[4] != 'for_user': + raise template.TemplateSyntaxError( + "Fourth argument to 'get_admin_log' must be 'for_user'") + return AdminLogNode(limit=tokens[1], varname=tokens[3], user=(len(tokens) > 5 and tokens[5] or None)) diff --git a/django/contrib/admin/views/decorators.py b/django/contrib/admin/views/decorators.py index 9fabe64a6a..b5313a162e 100644 --- a/django/contrib/admin/views/decorators.py +++ b/django/contrib/admin/views/decorators.py @@ -9,6 +9,7 @@ def staff_member_required(view_func): Decorator for views that checks that the user is logged in and is a staff member, displaying the login page if necessary. """ + @wraps(view_func) def _checklogin(request, *args, **kwargs): if request.user.is_active and request.user.is_staff: # The user is valid. Continue to the admin page. @@ -25,4 +26,4 @@ def staff_member_required(view_func): }, } return login(request, **defaults) - return wraps(view_func)(_checklogin) + return _checklogin diff --git a/django/contrib/admindocs/views.py b/django/contrib/admindocs/views.py index ba81337e92..319b489e46 100644 --- a/django/contrib/admindocs/views.py +++ b/django/contrib/admindocs/views.py @@ -27,22 +27,23 @@ def get_root_path(): except urlresolvers.NoReverseMatch: return getattr(settings, "ADMIN_SITE_ROOT_URL", "/admin/") +@staff_member_required def doc_index(request): if not utils.docutils_is_available: return missing_docutils_page(request) return render_to_response('admin_doc/index.html', { 'root_path': get_root_path(), }, context_instance=RequestContext(request)) -doc_index = staff_member_required(doc_index) +@staff_member_required def bookmarklets(request): admin_root = get_root_path() return render_to_response('admin_doc/bookmarklets.html', { 'root_path': admin_root, 'admin_url': mark_safe("%s://%s%s" % (request.is_secure() and 'https' or 'http', request.get_host(), admin_root)), }, context_instance=RequestContext(request)) -bookmarklets = staff_member_required(bookmarklets) +@staff_member_required def template_tag_index(request): if not utils.docutils_is_available: return missing_docutils_page(request) @@ -76,8 +77,8 @@ def template_tag_index(request): 'root_path': get_root_path(), 'tags': tags }, context_instance=RequestContext(request)) -template_tag_index = staff_member_required(template_tag_index) +@staff_member_required def template_filter_index(request): if not utils.docutils_is_available: return missing_docutils_page(request) @@ -111,8 +112,8 @@ def template_filter_index(request): 'root_path': get_root_path(), 'filters': filters }, context_instance=RequestContext(request)) -template_filter_index = staff_member_required(template_filter_index) +@staff_member_required def view_index(request): if not utils.docutils_is_available: return missing_docutils_page(request) @@ -142,8 +143,8 @@ def view_index(request): 'root_path': get_root_path(), 'views': views }, context_instance=RequestContext(request)) -view_index = staff_member_required(view_index) +@staff_member_required def view_detail(request, view): if not utils.docutils_is_available: return missing_docutils_page(request) @@ -167,8 +168,8 @@ def view_detail(request, view): 'body': body, 'meta': metadata, }, context_instance=RequestContext(request)) -view_detail = staff_member_required(view_detail) +@staff_member_required def model_index(request): if not utils.docutils_is_available: return missing_docutils_page(request) @@ -177,8 +178,8 @@ def model_index(request): 'root_path': get_root_path(), 'models': m_list }, context_instance=RequestContext(request)) -model_index = staff_member_required(model_index) +@staff_member_required def model_detail(request, app_label, model_name): if not utils.docutils_is_available: return missing_docutils_page(request) @@ -272,8 +273,8 @@ def model_detail(request, app_label, model_name): 'description': model.__doc__, 'fields': fields, }, context_instance=RequestContext(request)) -model_detail = staff_member_required(model_detail) +@staff_member_required def template_detail(request, template): templates = [] for site_settings_module in settings.ADMIN_FOR: @@ -297,7 +298,6 @@ def template_detail(request, template): 'name': template, 'templates': templates, }, context_instance=RequestContext(request)) -template_detail = staff_member_required(template_detail) #################### # Helper functions # diff --git a/django/contrib/comments/templatetags/comments.py b/django/contrib/comments/templatetags/comments.py index 8bc61cd445..7962a40d97 100644 --- a/django/contrib/comments/templatetags/comments.py +++ b/django/contrib/comments/templatetags/comments.py @@ -14,7 +14,7 @@ class BaseCommentNode(template.Node): obvious. """ - #@classmethod + @classmethod def handle_token(cls, parser, token): """Class method to parse get_comment_list/count/form and return a Node.""" tokens = token.contents.split() @@ -43,9 +43,7 @@ class BaseCommentNode(template.Node): else: raise template.TemplateSyntaxError("%r tag requires 4 or 5 arguments" % tokens[0]) - handle_token = classmethod(handle_token) - - #@staticmethod + @staticmethod def lookup_content_type(token, tagname): try: app, model = token.split('.') @@ -54,7 +52,6 @@ class BaseCommentNode(template.Node): raise template.TemplateSyntaxError("Third argument in %r must be in the format 'app.model'" % tagname) except ContentType.DoesNotExist: raise template.TemplateSyntaxError("%r tag has non-existant content-type: '%s.%s'" % (tagname, app, model)) - lookup_content_type = staticmethod(lookup_content_type) def __init__(self, ctype=None, object_pk_expr=None, object_expr=None, as_varname=None, comment=None): if ctype is None and object_expr is None: @@ -146,7 +143,7 @@ class CommentFormNode(BaseCommentNode): class RenderCommentFormNode(CommentFormNode): """Render the comment form directly""" - #@classmethod + @classmethod def handle_token(cls, parser, token): """Class method to parse render_comment_form and return a Node.""" tokens = token.contents.split() @@ -163,7 +160,6 @@ class RenderCommentFormNode(CommentFormNode): ctype = BaseCommentNode.lookup_content_type(tokens[2], tokens[0]), object_pk_expr = parser.compile_filter(tokens[3]) ) - handle_token = classmethod(handle_token) def render(self, context): ctype, object_pk = self.get_target_ctype_pk(context) @@ -183,7 +179,7 @@ class RenderCommentFormNode(CommentFormNode): class RenderCommentListNode(CommentListNode): """Render the comment list directly""" - #@classmethod + @classmethod def handle_token(cls, parser, token): """Class method to parse render_comment_list and return a Node.""" tokens = token.contents.split() @@ -200,7 +196,6 @@ class RenderCommentListNode(CommentListNode): ctype = BaseCommentNode.lookup_content_type(tokens[2], tokens[0]), object_pk_expr = parser.compile_filter(tokens[3]) ) - handle_token = classmethod(handle_token) def render(self, context): ctype, object_pk = self.get_target_ctype_pk(context) @@ -224,7 +219,7 @@ class RenderCommentListNode(CommentListNode): # the automagic docstrings-into-admin-docs tricks. So each node gets a cute # wrapper function that just exists to hold the docstring. -#@register.tag +@register.tag def get_comment_count(parser, token): """ Gets the comment count for the given params and populates the template @@ -245,7 +240,7 @@ def get_comment_count(parser, token): """ return CommentCountNode.handle_token(parser, token) -#@register.tag +@register.tag def get_comment_list(parser, token): """ Gets the list of comments for the given params and populates the template @@ -267,7 +262,7 @@ def get_comment_list(parser, token): """ return CommentListNode.handle_token(parser, token) -#@register.tag +@register.tag def render_comment_list(parser, token): """ Render the comment list (as returned by ``{% get_comment_list %}``) @@ -285,7 +280,7 @@ def render_comment_list(parser, token): """ return RenderCommentListNode.handle_token(parser, token) -#@register.tag +@register.tag def get_comment_form(parser, token): """ Get a (new) form object to post a new comment. @@ -297,7 +292,7 @@ def get_comment_form(parser, token): """ return CommentFormNode.handle_token(parser, token) -#@register.tag +@register.tag def render_comment_form(parser, token): """ Render the comment form (as returned by ``{% render_comment_form %}``) through @@ -310,7 +305,7 @@ def render_comment_form(parser, token): """ return RenderCommentFormNode.handle_token(parser, token) -#@register.simple_tag +@register.simple_tag def comment_form_target(): """ Get the target URL for the comment form. @@ -321,7 +316,7 @@ def comment_form_target(): """ return comments.get_form_target() -#@register.simple_tag +@register.simple_tag def get_comment_permalink(comment, anchor_pattern=None): """ Get the permalink for a comment, optionally specifying the format of the @@ -335,10 +330,3 @@ def get_comment_permalink(comment, anchor_pattern=None): return comment.get_absolute_url(anchor_pattern) return comment.get_absolute_url() -register.tag(get_comment_count) -register.tag(get_comment_list) -register.tag(get_comment_form) -register.tag(render_comment_form) -register.simple_tag(comment_form_target) -register.simple_tag(get_comment_permalink) -register.tag(render_comment_list) diff --git a/django/contrib/contenttypes/generic.py b/django/contrib/contenttypes/generic.py index 64c1f8b420..81301cfce1 100644 --- a/django/contrib/contenttypes/generic.py +++ b/django/contrib/contenttypes/generic.py @@ -339,13 +339,12 @@ class BaseGenericInlineFormSet(BaseModelFormSet): prefix=prefix ) - #@classmethod + @classmethod def get_default_prefix(cls): opts = cls.model._meta return '-'.join((opts.app_label, opts.object_name.lower(), cls.ct_field.name, cls.ct_fk_field.name, )) - get_default_prefix = classmethod(get_default_prefix) def save_new(self, form, commit=True): # Avoid a circular import. diff --git a/django/contrib/flatpages/templatetags/flatpages.py b/django/contrib/flatpages/templatetags/flatpages.py index 593f35c0e3..702d968145 100644 --- a/django/contrib/flatpages/templatetags/flatpages.py +++ b/django/contrib/flatpages/templatetags/flatpages.py @@ -38,6 +38,7 @@ class FlatpageNode(template.Node): return '' +@register.tag def get_flatpages(parser, token): """ Retrieves all flatpage objects available for the current site and @@ -94,5 +95,3 @@ def get_flatpages(parser, token): return FlatpageNode(context_name, starts_with=prefix, user=user) else: raise template.TemplateSyntaxError(syntax_message) - -register.tag('get_flatpages', get_flatpages) diff --git a/django/contrib/humanize/templatetags/humanize.py b/django/contrib/humanize/templatetags/humanize.py index 5f3e2a7aed..eee2b4d4f9 100644 --- a/django/contrib/humanize/templatetags/humanize.py +++ b/django/contrib/humanize/templatetags/humanize.py @@ -77,6 +77,7 @@ def apnumber(value): apnumber.is_safe = True register.filter(apnumber) +@register.filter def naturalday(value, arg=None): """ For date values that are tomorrow, today or yesterday compared to @@ -101,8 +102,8 @@ def naturalday(value, arg=None): elif delta.days == -1: return _(u'yesterday') return defaultfilters.date(value, arg) -register.filter(naturalday) +@register.filter def naturaltime(value, arg=None): """ For date and time values shows how many seconds, minutes or hours ago compared to @@ -133,4 +134,3 @@ def naturaltime(value, arg=None): elif delta.seconds / 60 / 60 < 24: return _(u'%s hours ago' % (delta.seconds/60/60)) return naturalday(value, arg) -register.filter(naturaltime) diff --git a/django/contrib/webdesign/templatetags/webdesign.py b/django/contrib/webdesign/templatetags/webdesign.py index 1eb1790132..05d8dc7f54 100644 --- a/django/contrib/webdesign/templatetags/webdesign.py +++ b/django/contrib/webdesign/templatetags/webdesign.py @@ -20,7 +20,7 @@ class LoremNode(template.Node): paras = ['

%s

' % p for p in paras] return u'\n\n'.join(paras) -#@register.tag +@register.tag def lorem(parser, token): """ Creates random Latin text useful for providing test data in templates. @@ -64,4 +64,3 @@ def lorem(parser, token): if len(bits) != 1: raise template.TemplateSyntaxError("Incorrect format for %r tag" % tagname) return LoremNode(count, method, common) -lorem = register.tag(lorem) diff --git a/django/forms/formsets.py b/django/forms/formsets.py index da92fbd408..3810ebf7fd 100644 --- a/django/forms/formsets.py +++ b/django/forms/formsets.py @@ -218,10 +218,9 @@ class BaseFormSet(StrAndUnicode): return [self.forms[i[0]] for i in self._ordering] ordered_forms = property(_get_ordered_forms) - #@classmethod + @classmethod def get_default_prefix(cls): return 'form' - get_default_prefix = classmethod(get_default_prefix) def non_form_errors(self): """ diff --git a/django/forms/models.py b/django/forms/models.py index 9c1287f065..ecfdc92182 100644 --- a/django/forms/models.py +++ b/django/forms/models.py @@ -701,11 +701,10 @@ class BaseInlineFormSet(BaseModelFormSet): setattr(form.instance, self.fk.get_attname(), self.instance.pk) return form - #@classmethod + @classmethod def get_default_prefix(cls): from django.db.models.fields.related import RelatedObject return RelatedObject(cls.fk.rel.to, cls.model, cls.fk).get_accessor_name().replace('+','') - get_default_prefix = classmethod(get_default_prefix) def save_new(self, form, commit=True): # Use commit=False so we can assign the parent key afterwards, then diff --git a/django/template/base.py b/django/template/base.py index b6470f3e91..087c86d5ea 100644 --- a/django/template/base.py +++ b/django/template/base.py @@ -823,7 +823,7 @@ class Library(object): # @register.tag() return self.tag_function elif name != None and compile_function == None: - if(callable(name)): + if callable(name): # @register.tag return self.tag_function(name) else: @@ -847,7 +847,7 @@ class Library(object): # @register.filter() return self.filter_function elif filter_func == None: - if(callable(name)): + if callable(name): # @register.filter return self.filter_function(name) else: diff --git a/django/template/defaulttags.py b/django/template/defaulttags.py index f4018ab427..ea49c1932c 100644 --- a/django/template/defaulttags.py +++ b/django/template/defaulttags.py @@ -501,7 +501,7 @@ class WithNode(Node): context.pop() return output -#@register.tag +@register.tag def autoescape(parser, token): """ Force autoescape behaviour for this block. @@ -515,18 +515,16 @@ def autoescape(parser, token): nodelist = parser.parse(('endautoescape',)) parser.delete_first_token() return AutoEscapeControlNode((arg == 'on'), nodelist) -autoescape = register.tag(autoescape) -#@register.tag +@register.tag def comment(parser, token): """ Ignores everything between ``{% comment %}`` and ``{% endcomment %}``. """ parser.skip_past('endcomment') return CommentNode() -comment = register.tag(comment) -#@register.tag +@register.tag def cycle(parser, token): """ Cycles among the given strings each time this tag is encountered. @@ -617,12 +615,12 @@ def cycle(parser, token): values = [parser.compile_filter(arg) for arg in args[1:]] node = CycleNode(values) return node -cycle = register.tag(cycle) +@register.tag def csrf_token(parser, token): return CsrfTokenNode() -register.tag(csrf_token) +@register.tag def debug(parser, token): """ Outputs a whole load of debugging information, including the current @@ -635,9 +633,8 @@ def debug(parser, token): """ return DebugNode() -debug = register.tag(debug) -#@register.tag(name="filter") +@register.tag('filter') def do_filter(parser, token): """ Filters the contents of the block through variable filters. @@ -659,9 +656,8 @@ def do_filter(parser, token): nodelist = parser.parse(('endfilter',)) parser.delete_first_token() return FilterNode(filter_expr, nodelist) -do_filter = register.tag("filter", do_filter) -#@register.tag +@register.tag def firstof(parser, token): """ Outputs the first variable passed that is not False, without escaping. @@ -700,9 +696,8 @@ def firstof(parser, token): if len(bits) < 1: raise TemplateSyntaxError("'firstof' statement requires at least one argument") return FirstOfNode([parser.compile_filter(bit) for bit in bits]) -firstof = register.tag(firstof) -#@register.tag(name="for") +@register.tag('for') def do_for(parser, token): """ Loops over each item in an array. @@ -792,7 +787,6 @@ def do_for(parser, token): else: nodelist_empty = None return ForNode(loopvars, sequence, is_reversed, nodelist_loop, nodelist_empty) -do_for = register.tag("for", do_for) def do_ifequal(parser, token, negate): bits = list(token.split_contents()) @@ -810,7 +804,7 @@ def do_ifequal(parser, token, negate): val2 = parser.compile_filter(bits[2]) return IfEqualNode(val1, val2, nodelist_true, nodelist_false, negate) -#@register.tag +@register.tag def ifequal(parser, token): """ Outputs the contents of the block if the two arguments equal each other. @@ -828,16 +822,14 @@ def ifequal(parser, token): {% endifnotequal %} """ return do_ifequal(parser, token, False) -ifequal = register.tag(ifequal) -#@register.tag +@register.tag def ifnotequal(parser, token): """ Outputs the contents of the block if the two arguments are not equal. See ifequal. """ return do_ifequal(parser, token, True) -ifnotequal = register.tag(ifnotequal) class TemplateLiteral(Literal): def __init__(self, value, text): @@ -860,7 +852,7 @@ class TemplateIfParser(IfParser): def create_var(self, value): return TemplateLiteral(self.template_parser.compile_filter(value), value) -#@register.tag(name="if") +@register.tag('if') def do_if(parser, token): """ The ``{% if %}`` tag evaluates a variable, and if that variable is "true" @@ -927,9 +919,8 @@ def do_if(parser, token): else: nodelist_false = NodeList() return IfNode(var, nodelist_true, nodelist_false) -do_if = register.tag("if", do_if) -#@register.tag +@register.tag def ifchanged(parser, token): """ Checks if a value has changed from the last iteration of a loop. @@ -968,9 +959,8 @@ def ifchanged(parser, token): nodelist_false = NodeList() values = [parser.compile_filter(bit) for bit in bits[1:]] return IfChangedNode(nodelist_true, nodelist_false, *values) -ifchanged = register.tag(ifchanged) -#@register.tag +@register.tag def ssi(parser, token): """ Outputs the contents of a given file into the page. @@ -1003,9 +993,8 @@ def ssi(parser, token): raise TemplateSyntaxError("Second (optional) argument to %s tag" " must be 'parsed'" % bits[0]) return SsiNode(bits[1], parsed, legacy_filepath=True) -ssi = register.tag(ssi) -#@register.tag +@register.tag def load(parser, token): """ Loads a custom template tag set. @@ -1053,9 +1042,8 @@ def load(parser, token): raise TemplateSyntaxError("'%s' is not a valid tag library: %s" % (taglib, e)) return LoadNode() -load = register.tag(load) -#@register.tag +@register.tag def now(parser, token): """ Displays the date, formatted according to the given string. @@ -1072,9 +1060,8 @@ def now(parser, token): raise TemplateSyntaxError("'now' statement takes one argument") format_string = bits[1] return NowNode(format_string) -now = register.tag(now) -#@register.tag +@register.tag def regroup(parser, token): """ Regroups a list of alike objects by a common attribute. @@ -1136,8 +1123,8 @@ def regroup(parser, token): var_name = lastbits_reversed[0][::-1] return RegroupNode(target, expression, var_name) -regroup = register.tag(regroup) +@register.tag def spaceless(parser, token): """ Removes whitespace between HTML tags, including tab and newline characters. @@ -1166,9 +1153,8 @@ def spaceless(parser, token): nodelist = parser.parse(('endspaceless',)) parser.delete_first_token() return SpacelessNode(nodelist) -spaceless = register.tag(spaceless) -#@register.tag +@register.tag def templatetag(parser, token): """ Outputs one of the bits used to compose template tags. @@ -1200,8 +1186,8 @@ def templatetag(parser, token): " Must be one of: %s" % (tag, TemplateTagNode.mapping.keys())) return TemplateTagNode(tag) -templatetag = register.tag(templatetag) +@register.tag def url(parser, token): """ Returns an absolute URL matching given view with its parameters. @@ -1299,9 +1285,8 @@ def url(parser, token): args.append(parser.compile_filter(value)) return URLNode(viewname, args, kwargs, asvar, legacy_view_name=True) -url = register.tag(url) -#@register.tag +@register.tag def widthratio(parser, token): """ For creating bar charts and such, this tag calculates the ratio of a given @@ -1323,9 +1308,8 @@ def widthratio(parser, token): return WidthRatioNode(parser.compile_filter(this_value_expr), parser.compile_filter(max_value_expr), parser.compile_filter(max_width)) -widthratio = register.tag(widthratio) -#@register.tag +@register.tag('with') def do_with(parser, token): """ Adds one or more values to the context (inside of this block) for caching @@ -1358,4 +1342,3 @@ def do_with(parser, token): nodelist = parser.parse(('endwith',)) parser.delete_first_token() return WithNode(None, None, nodelist, extra_context=extra_context) -do_with = register.tag('with', do_with) diff --git a/django/template/loader_tags.py b/django/template/loader_tags.py index e289ef0d9e..f5cac33dc6 100644 --- a/django/template/loader_tags.py +++ b/django/template/loader_tags.py @@ -173,6 +173,7 @@ class IncludeNode(BaseIncludeNode): raise return '' +@register.tag('block') def do_block(parser, token): """ Define a block that can be overridden by child templates. @@ -193,6 +194,7 @@ def do_block(parser, token): parser.delete_first_token() return BlockNode(block_name, nodelist) +@register.tag('extends') def do_extends(parser, token): """ Signal that this template extends a parent template. @@ -216,6 +218,7 @@ def do_extends(parser, token): raise TemplateSyntaxError("'%s' cannot appear more than once in the same template" % bits[0]) return ExtendsNode(nodelist, parent_name, parent_name_expr) +@register.tag('include') def do_include(parser, token): """ Loads a template and renders it with the current context. You can pass @@ -261,7 +264,3 @@ def do_include(parser, token): isolated_context=isolated_context) return IncludeNode(parser.compile_filter(bits[1]), extra_context=namemap, isolated_context=isolated_context) - -register.tag('block', do_block) -register.tag('extends', do_extends) -register.tag('include', do_include) diff --git a/django/templatetags/cache.py b/django/templatetags/cache.py index 0440d10cb8..495623deaf 100644 --- a/django/templatetags/cache.py +++ b/django/templatetags/cache.py @@ -32,6 +32,7 @@ class CacheNode(Node): cache.set(cache_key, value, expire_time) return value +@register.tag('cache') def do_cache(parser, token): """ This will cache the contents of a template fragment for a given amount @@ -59,5 +60,3 @@ def do_cache(parser, token): if len(tokens) < 3: raise TemplateSyntaxError(u"'%r' tag requires at least 2 arguments." % tokens[0]) return CacheNode(nodelist, tokens[1], tokens[2], tokens[3:]) - -register.tag('cache', do_cache) diff --git a/django/templatetags/i18n.py b/django/templatetags/i18n.py index e6b3b6132a..17821367a6 100644 --- a/django/templatetags/i18n.py +++ b/django/templatetags/i18n.py @@ -117,6 +117,7 @@ class BlockTranslateNode(Node): context.pop() return result % data +@register.tag("get_available_languages") def do_get_available_languages(parser, token): """ This will store a list of available languages @@ -138,6 +139,7 @@ def do_get_available_languages(parser, token): raise TemplateSyntaxError("'get_available_languages' requires 'as variable' (got %r)" % args) return GetAvailableLanguagesNode(args[2]) +@register.tag("get_language_info") def do_get_language_info(parser, token): """ This will store the language information dictionary for the given language @@ -156,6 +158,7 @@ def do_get_language_info(parser, token): raise TemplateSyntaxError("'%s' requires 'for string as variable' (got %r)" % (args[0], args[1:])) return GetLanguageInfoNode(args[2], args[4]) +@register.tag("get_language_info_list") def do_get_language_info_list(parser, token): """ This will store a list of language information dictionaries for the given @@ -178,15 +181,19 @@ def do_get_language_info_list(parser, token): raise TemplateSyntaxError("'%s' requires 'for sequence as variable' (got %r)" % (args[0], args[1:])) return GetLanguageInfoListNode(args[2], args[4]) +@register.filter def language_name(lang_code): return translation.get_language_info(lang_code)['name'] +@register.filter def language_name_local(lang_code): return translation.get_language_info(lang_code)['name_local'] +@register.filter def language_bidi(lang_code): return translation.get_language_info(lang_code)['bidi'] +@register.tag("get_current_language") def do_get_current_language(parser, token): """ This will store the current language in the context. @@ -204,6 +211,7 @@ def do_get_current_language(parser, token): raise TemplateSyntaxError("'get_current_language' requires 'as variable' (got %r)" % args) return GetCurrentLanguageNode(args[2]) +@register.tag("get_current_language_bidi") def do_get_current_language_bidi(parser, token): """ This will store the current language layout in the context. @@ -221,6 +229,7 @@ def do_get_current_language_bidi(parser, token): raise TemplateSyntaxError("'get_current_language_bidi' requires 'as variable' (got %r)" % args) return GetCurrentLanguageBidiNode(args[2]) +@register.tag("trans") def do_translate(parser, token): """ This will mark a string for translation and will @@ -279,6 +288,7 @@ def do_translate(parser, token): value, noop = TranslateParser(token.contents).top() return TranslateNode(parser.compile_filter(value), noop) +@register.tag("blocktrans") def do_block_translate(parser, token): """ This will translate a block of text with parameters. @@ -356,15 +366,3 @@ def do_block_translate(parser, token): return BlockTranslateNode(extra_context, singular, plural, countervar, counter) - -register.tag('get_available_languages', do_get_available_languages) -register.tag('get_language_info', do_get_language_info) -register.tag('get_language_info_list', do_get_language_info_list) -register.tag('get_current_language', do_get_current_language) -register.tag('get_current_language_bidi', do_get_current_language_bidi) -register.tag('trans', do_translate) -register.tag('blocktrans', do_block_translate) - -register.filter(language_name) -register.filter(language_name_local) -register.filter(language_bidi) diff --git a/django/utils/decorators.py b/django/utils/decorators.py index 6099f88266..ee169ec7cc 100644 --- a/django/utils/decorators.py +++ b/django/utils/decorators.py @@ -77,6 +77,7 @@ def make_middleware_decorator(middleware_class): def _make_decorator(*m_args, **m_kwargs): middleware = middleware_class(*m_args, **m_kwargs) def _decorator(view_func): + @wraps(view_func, assigned=available_attrs(view_func)) def _wrapped_view(request, *args, **kwargs): if hasattr(middleware, 'process_request'): result = middleware.process_request(request) @@ -99,6 +100,6 @@ def make_middleware_decorator(middleware_class): if result is not None: return result return response - return wraps(view_func, assigned=available_attrs(view_func))(_wrapped_view) + return _wrapped_view return _decorator return _make_decorator diff --git a/django/utils/functional.py b/django/utils/functional.py index ee0f09a9ee..9635bf92a6 100644 --- a/django/utils/functional.py +++ b/django/utils/functional.py @@ -17,6 +17,7 @@ def memoize(func, cache, num_args): Only the first num_args are considered when creating the key. """ + @wraps(func) def wrapper(*args): mem_args = args[:num_args] if mem_args in cache: @@ -24,7 +25,7 @@ def memoize(func, cache, num_args): result = func(*args) cache[mem_args] = result return result - return wraps(func)(wrapper) + return wrapper class Promise(object): """ @@ -135,11 +136,12 @@ def lazy(func, *resultclasses): memo[id(self)] = self return self + @wraps(func) def __wrapper__(*args, **kw): # Creates the proxy object, instead of the actual value. return __proxy__(args, kw) - return wraps(func)(__wrapper__) + return __wrapper__ def _lazy_proxy_unpickle(func, args, kwargs, *resultclasses): return lazy(func, *resultclasses)(*args, **kwargs) @@ -151,6 +153,7 @@ def allow_lazy(func, *resultclasses): immediately, otherwise a __proxy__ is returned that will evaluate the function when needed. """ + @wraps(func) def wrapper(*args, **kwargs): for arg in list(args) + kwargs.values(): if isinstance(arg, Promise): @@ -158,7 +161,7 @@ def allow_lazy(func, *resultclasses): else: return func(*args, **kwargs) return lazy(func, *resultclasses)(*args, **kwargs) - return wraps(func)(wrapper) + return wrapper class LazyObject(object): """ diff --git a/django/views/decorators/cache.py b/django/views/decorators/cache.py index 279649d35f..d96d71651e 100644 --- a/django/views/decorators/cache.py +++ b/django/views/decorators/cache.py @@ -58,11 +58,12 @@ def cache_page(*args, **kwargs): def cache_control(**kwargs): def _cache_controller(viewfunc): + @wraps(viewfunc, assigned=available_attrs(viewfunc)) def _cache_controlled(request, *args, **kw): response = viewfunc(request, *args, **kw) patch_cache_control(response, **kwargs) return response - return wraps(viewfunc, assigned=available_attrs(viewfunc))(_cache_controlled) + return _cache_controlled return _cache_controller @@ -71,8 +72,9 @@ def never_cache(view_func): Decorator that adds headers to a response so that it will never be cached. """ + @wraps(view_func, assigned=available_attrs(view_func)) def _wrapped_view_func(request, *args, **kwargs): response = view_func(request, *args, **kwargs) add_never_cache_headers(response) return response - return wraps(view_func, assigned=available_attrs(view_func))(_wrapped_view_func) + return _wrapped_view_func diff --git a/django/views/decorators/http.py b/django/views/decorators/http.py index 054dc57c35..6fc882efa7 100644 --- a/django/views/decorators/http.py +++ b/django/views/decorators/http.py @@ -29,6 +29,7 @@ def require_http_methods(request_method_list): Note that request methods should be in uppercase. """ def decorator(func): + @wraps(func, assigned=available_attrs(func)) def inner(request, *args, **kwargs): if request.method not in request_method_list: logger.warning('Method Not Allowed (%s): %s' % (request.method, request.path), @@ -39,7 +40,7 @@ def require_http_methods(request_method_list): ) return HttpResponseNotAllowed(request_method_list) return func(request, *args, **kwargs) - return wraps(func, assigned=available_attrs(func))(inner) + return inner return decorator require_GET = require_http_methods(["GET"]) diff --git a/django/views/decorators/vary.py b/django/views/decorators/vary.py index 939b8c3413..cd2f9c0f55 100644 --- a/django/views/decorators/vary.py +++ b/django/views/decorators/vary.py @@ -14,11 +14,12 @@ def vary_on_headers(*headers): Note that the header names are not case-sensitive. """ def decorator(func): + @wraps(func, assigned=available_attrs(func)) def inner_func(*args, **kwargs): response = func(*args, **kwargs) patch_vary_headers(response, headers) return response - return wraps(func, assigned=available_attrs(func))(inner_func) + return inner_func return decorator def vary_on_cookie(func): @@ -30,8 +31,9 @@ def vary_on_cookie(func): def index(request): ... """ + @wraps(func, assigned=available_attrs(func)) def inner_func(*args, **kwargs): response = func(*args, **kwargs) patch_vary_headers(response, ('Cookie',)) return response - return wraps(func, assigned=available_attrs(func))(inner_func) + return inner_func diff --git a/tests/modeltests/select_for_update/tests.py b/tests/modeltests/select_for_update/tests.py index 2e4eaed447..24e6d748e7 100644 --- a/tests/modeltests/select_for_update/tests.py +++ b/tests/modeltests/select_for_update/tests.py @@ -6,7 +6,6 @@ from django.db import transaction, connection from django.db.utils import ConnectionHandler, DEFAULT_DB_ALIAS, DatabaseError from django.test import (TransactionTestCase, skipIfDBFeature, skipUnlessDBFeature) -from django.utils.functional import wraps from django.utils import unittest from models import Person diff --git a/tests/regressiontests/admin_views/views.py b/tests/regressiontests/admin_views/views.py index 732b2535b9..bb5f24ebfe 100644 --- a/tests/regressiontests/admin_views/views.py +++ b/tests/regressiontests/admin_views/views.py @@ -1,6 +1,6 @@ from django.contrib.admin.views.decorators import staff_member_required from django.http import HttpResponse +@staff_member_required def secure_view(request): return HttpResponse('%s' % request.POST) -secure_view = staff_member_required(secure_view) \ No newline at end of file