Opened 3 years ago

Closed 2 years ago

#33653 closed Bug (fixed)

Templates crash when calling methods for built-in types.

Reported by: Daniel Owned by: Cheng Yuan
Component: Template system Version: 3.2
Severity: Normal Keywords: template
Cc: Baptiste Mispelon Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Daniel)

Found during a 2.2 -> 3.2 upgrade:

Given a template:

{{ foo }}

where foo is non-existant, it returns nothing, empty. (That's good)

{{ foo.count }}

also empty (Also good)

{% include 'second_template.html' with bar=foo %}

and then in second_template.html having:

{{ bar.count }}

results in

  File "/Users/daniel/src/django-bug-test/.v/lib/python3.8/site-packages/django/template/base.py", line 861, in _resolve_lookup
    signature = inspect.signature(current)
  File "/Users/daniel/.pyenv/versions/3.8.3/lib/python3.8/inspect.py", line 3093, in signature
    return Signature.from_callable(obj, follow_wrapped=follow_wrapped)
  File "/Users/daniel/.pyenv/versions/3.8.3/lib/python3.8/inspect.py", line 2842, in from_callable
    return _signature_from_callable(obj, sigcls=cls,
  File "/Users/daniel/.pyenv/versions/3.8.3/lib/python3.8/inspect.py", line 2296, in _signature_from_callable
    return _signature_from_builtin(sigcls, obj,
  File "/Users/daniel/.pyenv/versions/3.8.3/lib/python3.8/inspect.py", line 2107, in _signature_from_builtin
    raise ValueError("no signature found for builtin {!r}".format(func))

Exception Type: ValueError at /
Exception Value: no signature found for builtin <built-in method count of str object at 0x1100ff2f0>

On django 2.2, this would not crash, but resulted in empty (as I expected).

this seems to fix it for me:

diff --git a/django/template/base.py b/django/template/base.py
index a1ab437eca..f95aec5a90 100644
--- a/django/template/base.py
+++ b/django/template/base.py
@@ -913,15 +913,19 @@ def _resolve_lookup(self, context):
                         try:  # method call (assuming no args required)
                             current = current()
                         except TypeError:
-                            signature = inspect.signature(current)
                             try:
-                                signature.bind()
-                            except TypeError:  # arguments *were* required
-                                current = (
-                                    context.template.engine.string_if_invalid
-                                )  # invalid method call
+                                signature = inspect.signature(current)
+                            except ValueError: # python builtins might not have signature
+                                current = context.template.engine.string_if_invalid
                             else:
-                                raise
+                                try:
+                                    signature.bind()
+                                except TypeError:  # arguments *were* required
+                                    current = (
+                                        context.template.engine.string_if_invalid
+                                    )  # invalid method call
+                                else:
+                                    raise
         except Exception as e:
             template_name = getattr(context, "template_name", None) or "unknown"
             logger.debug(

Change History (9)

comment:1 by Daniel, 3 years ago

Description: modified (diff)

comment:2 by jerch, 3 years ago

Isn't a bug, that the template resolver tries to step into ''.<some_builtin_method> here? Maybe the for bit in self.lookups: descent could exit as soon as current drops to an empty string?

comment:3 by Mariusz Felisiak, 3 years ago

Cc: Baptiste Mispelon added
Summary: no signature found for builtin raised for non-existant itemsTemplates crash when calling methods for built-in types.
Triage Stage: UnreviewedAccepted

Thanks for the report. foo may exist, the same error is raised for each method call for bultin types, e.g.

def myview(request):
    return render(request, "myview.html", {"foo": "X"})

myview.html:

{{foo.count}}

Regression in 09341856ed9008875c1cc883dc0c287670131458.

Last edited 3 years ago by Mariusz Felisiak (previous) (diff)

comment:4 by Cheng Yuan, 3 years ago

Owner: changed from nobody to Cheng Yuan
Status: newassigned

comment:6 by Mariusz Felisiak, 3 years ago

Needs tests: set
Patch needs improvement: set

comment:7 by Cheng Yuan, 3 years ago

Hi Mariusz,

Just saw the flag Patch needs improvement is checked. How exactly should I improve the patch, besides that I need to add tests (or only tests need to be added)?
I'm a first-time Django contributor any help is appreciated!

Cheng

comment:8 by Mariusz Felisiak, 2 years ago

Needs tests: unset
Patch needs improvement: unset
Triage Stage: AcceptedReady for checkin

comment:9 by Mariusz Felisiak <felisiak.mariusz@…>, 2 years ago

Resolution: fixed
Status: assignedclosed

In 0dd29209:

Fixed #33653 -- Fixed template crash when calling methods for built-in types without required arguments.

Regression in 09341856ed9008875c1cc883dc0c287670131458.

Note: See TracTickets for help on using tickets.
Back to Top