|
| 1 | +From 065334d1ee5b7210e1a0a93c37238c86858f2af7 Mon Sep 17 00:00:00 2001 |
| 2 | +From: David Lord <davidism@gmail.com> |
| 3 | +Date: Wed, 5 Mar 2025 10:08:48 -0800 |
| 4 | +Subject: [PATCH] attr filter uses env.getattr |
| 5 | + |
| 6 | +--- |
| 7 | + deps/v8/third_party/jinja2/filters.py | 37 ++++++++++++++++--------------------- |
| 8 | + 3 files changed, 30 insertions(+), 21 deletions(-) |
| 9 | + |
| 10 | +diff --git a/deps/v8/third_party/jinja2/filters.py b/deps/v8/third_party/jinja2/filters.py |
| 11 | +index e5b5a00c5..2bcba4fbd 100644 |
| 12 | +--- a/deps/v8/third_party/jinja2/filters.py |
| 13 | ++++ b/deps/v8/third_party/jinja2/filters.py |
| 14 | +@@ -6,6 +6,7 @@ |
| 15 | + import typing |
| 16 | + import typing as t |
| 17 | + from collections import abc |
| 18 | ++from inspect import getattr_static |
| 19 | + from itertools import chain |
| 20 | + from itertools import groupby |
| 21 | + |
| 22 | +@@ -1411,31 +1412,25 @@ def do_reverse(value: t.Union[str, t.Iterable[V]]) -> t.Union[str, t.Iterable[V] |
| 23 | + def do_attr( |
| 24 | + environment: "Environment", obj: t.Any, name: str |
| 25 | + ) -> t.Union[Undefined, t.Any]: |
| 26 | +- """Get an attribute of an object. ``foo|attr("bar")`` works like |
| 27 | +- ``foo.bar`` just that always an attribute is returned and items are not |
| 28 | +- looked up. |
| 29 | ++ """Get an attribute of an object. ``foo|attr("bar")`` works like |
| 30 | ++ ``foo.bar``, but returns undefined instead of falling back to ``foo["bar"]`` |
| 31 | ++ if the attribute doesn't exist. |
| 32 | + |
| 33 | + See :ref:`Notes on subscriptions <notes-on-subscriptions>` for more details. |
| 34 | + """ |
| 35 | ++ # Environment.getattr will fall back to obj[name] if obj.name doesn't exist. |
| 36 | ++ # But we want to call env.getattr to get behavior such as sandboxing. |
| 37 | ++ # Determine if the attr exists first, so we know the fallback won't trigger. |
| 38 | + try: |
| 39 | +- name = str(name) |
| 40 | +- except UnicodeError: |
| 41 | +- pass |
| 42 | +- else: |
| 43 | +- try: |
| 44 | +- value = getattr(obj, name) |
| 45 | +- except AttributeError: |
| 46 | +- pass |
| 47 | +- else: |
| 48 | +- if environment.sandboxed: |
| 49 | +- environment = t.cast("SandboxedEnvironment", environment) |
| 50 | +- |
| 51 | +- if not environment.is_safe_attribute(obj, name, value): |
| 52 | +- return environment.unsafe_undefined(obj, name) |
| 53 | +- |
| 54 | +- return value |
| 55 | +- |
| 56 | +- return environment.undefined(obj=obj, name=name) |
| 57 | ++ # This avoids executing properties/descriptors, but misses __getattr__ |
| 58 | ++ # and __getattribute__ dynamic attrs. |
| 59 | ++ getattr_static(obj, name) |
| 60 | ++ except AttributeError: |
| 61 | ++ # This finds dynamic attrs, and we know it's not a descriptor at this point. |
| 62 | ++ if not hasattr(obj, name): |
| 63 | ++ return environment.undefined(obj=obj, name=name) |
| 64 | ++ |
| 65 | ++ return environment.getattr(obj, name) |
| 66 | + |
| 67 | + |
| 68 | + @typing.overload |
0 commit comments