Changed args_check parameters, Created class to verify deferred annotations only in python 3.14+ version

This commit is contained in:
Augusto Pontes 2025-11-10 17:46:06 -03:00
parent d03c80933a
commit 7d68cf8db0
2 changed files with 35 additions and 12 deletions

View file

@ -65,6 +65,7 @@ from django.utils.safestring import SafeData, SafeString, mark_safe
from django.utils.text import get_text_list, smart_split, unescape_string_literal
from django.utils.timezone import template_localtime
from django.utils.translation import gettext_lazy, pgettext_lazy
from django.utils.version import PY314
from .exceptions import TemplateSyntaxError
@ -92,6 +93,9 @@ tag_re = re.compile(r"({%.*?%}|{{.*?}}|{#.*?#})")
logger = logging.getLogger("django.template")
if PY314:
import annotationlib
class TokenType(Enum):
TEXT = 0
@ -825,20 +829,16 @@ class FilterExpression:
# Check to see if a decorator is providing the real function.
func = inspect.unwrap(func)
try:
# Using signature first(more modern)
if PY314:
sig = inspect.signature(func, annotation_format=annotationlib.Format.FORWARDREF)
else:
sig = inspect.signature(func)
alen = len(sig.parameters)
alen = len(sig.parameters)
non_default_params = [
p for p in sig.parameters.values() if p.default is p.empty
]
dlen = alen - len(non_default_params)
except (TypeError, ValueError):
# If fails, use the old getfullargspec(deprecated)
args, _, _, defaults, _, _, _ = inspect.getfullargspec(func)
alen = len(args)
dlen = len(defaults or [])
non_default_params = [
p for p in sig.parameters.values() if p.default is p.empty
]
dlen = alen - len(non_default_params)
# Not enough OR Too many
if plen < (alen - dlen) or plen > alen:

View file

@ -14,7 +14,16 @@ from django.template.base import (
VariableDoesNotExist,
)
from django.template.defaultfilters import register as filter_library
from django.utils.version import PY314
from django.test import SimpleTestCase
from django.template import Library
from django.utils.html import escape
from typing import TYPE_CHECKING
import unittest
if TYPE_CHECKING:
from django.utils.safestring import SafeText
class ParserTests(SimpleTestCase):
@ -240,3 +249,17 @@ class ParserTests(SimpleTestCase):
FilterExpression(num, p).resolve({})
with self.assertRaises(TemplateSyntaxError):
FilterExpression(f"0|default:{num}", p).resolve({})
class FilterExpressionArgsTests(unittest.TestCase):
@unittest.skipUnless(PY314, "Deferred annotations area Python 3.14+ only")
def test_register_filter_deferred_annotations(self):
register = Library()
@register.filter("example")
def example_filter(value: str) -> SafeText:
return escape(value)
result = example_filter("example")
self.assertTrue(result)