From 5c19274643dacc0a16e26634aa5dc34bd11a7077 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Batuhan=20Ta=C5=9Fkaya?= Date: Tue, 7 May 2019 05:02:08 +0300 Subject: [PATCH] Fixed #30453 -- Fixed crash of simple_tag() and inclusion_tag() when function is wrapped. getfullargspec() doesn't work with wrapped functions. --- AUTHORS | 1 + django/template/library.py | 6 +++--- tests/template_tests/test_library.py | 20 ++++++++++++++++++++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/AUTHORS b/AUTHORS index afc71f75e7b..8c4620797b4 100644 --- a/AUTHORS +++ b/AUTHORS @@ -107,6 +107,7 @@ answer newbie questions, and generally made Django that much better: Bastian Kleineidam Batiste Bieler Batman + Batuhan Taskaya Baurzhan Ismagulov Ben Dean Kawamura Ben Firshman diff --git a/django/template/library.py b/django/template/library.py index f88c2af8220..20bc86dac84 100644 --- a/django/template/library.py +++ b/django/template/library.py @@ -1,6 +1,6 @@ import functools from importlib import import_module -from inspect import getfullargspec +from inspect import getfullargspec, unwrap from django.utils.html import conditional_escape from django.utils.itercompat import is_iterable @@ -106,7 +106,7 @@ class Library: return 'world' """ def dec(func): - params, varargs, varkw, defaults, kwonly, kwonly_defaults, _ = getfullargspec(func) + params, varargs, varkw, defaults, kwonly, kwonly_defaults, _ = getfullargspec(unwrap(func)) function_name = (name or getattr(func, '_decorated_function', func).__name__) @functools.wraps(func) @@ -143,7 +143,7 @@ class Library: return {'choices': choices} """ def dec(func): - params, varargs, varkw, defaults, kwonly, kwonly_defaults, _ = getfullargspec(func) + params, varargs, varkw, defaults, kwonly, kwonly_defaults, _ = getfullargspec(unwrap(func)) function_name = (name or getattr(func, '_decorated_function', func).__name__) @functools.wraps(func) diff --git a/tests/template_tests/test_library.py b/tests/template_tests/test_library.py index b7a1f73a2e0..9fdb9b7aa1d 100644 --- a/tests/template_tests/test_library.py +++ b/tests/template_tests/test_library.py @@ -1,3 +1,5 @@ +import functools + from django.template import Library from django.template.base import Node from django.test import SimpleTestCase @@ -61,6 +63,15 @@ class InclusionTagRegistrationTests(SimpleTestCase): return '' self.assertIn('name', self.library.tags) + def test_inclusion_tag_wrapped(self): + @self.library.inclusion_tag('template.html') + @functools.lru_cache(maxsize=32) + def func(): + return '' + func_wrapped = self.library.tags['func'].__wrapped__ + self.assertIs(func_wrapped, func) + self.assertTrue(hasattr(func_wrapped, 'cache_info')) + class SimpleTagRegistrationTests(SimpleTestCase): @@ -90,6 +101,15 @@ class SimpleTagRegistrationTests(SimpleTestCase): with self.assertRaisesMessage(ValueError, msg): self.library.simple_tag('invalid') + def test_simple_tag_wrapped(self): + @self.library.simple_tag + @functools.lru_cache(maxsize=32) + def func(): + return '' + func_wrapped = self.library.tags['func'].__wrapped__ + self.assertIs(func_wrapped, func) + self.assertTrue(hasattr(func_wrapped, 'cache_info')) + class TagRegistrationTests(SimpleTestCase):