Speed up template result parsing (#118168)

This commit is contained in:
J. Nick Koston 2024-05-26 01:09:12 -10:00 committed by GitHub
parent 4a3808c08e
commit 607aaa0efe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -327,7 +327,33 @@ def _false(arg: str) -> bool:
return False
_cached_literal_eval = lru_cache(maxsize=EVAL_CACHE_SIZE)(literal_eval)
@lru_cache(maxsize=EVAL_CACHE_SIZE)
def _cached_parse_result(render_result: str) -> Any:
"""Parse a result and cache the result."""
result = literal_eval(render_result)
if type(result) in RESULT_WRAPPERS:
result = RESULT_WRAPPERS[type(result)](result, render_result=render_result)
# If the literal_eval result is a string, use the original
# render, by not returning right here. The evaluation of strings
# resulting in strings impacts quotes, to avoid unexpected
# output; use the original render instead of the evaluated one.
# Complex and scientific values are also unexpected. Filter them out.
if (
# Filter out string and complex numbers
not isinstance(result, (str, complex))
and (
# Pass if not numeric and not a boolean
not isinstance(result, (int, float))
# Or it's a boolean (inherit from int)
or isinstance(result, bool)
# Or if it's a digit
or _IS_NUMERIC.match(render_result) is not None
)
):
return result
return render_result
class RenderInfo:
@ -588,31 +614,7 @@ class Template:
def _parse_result(self, render_result: str) -> Any:
"""Parse the result."""
try:
result = _cached_literal_eval(render_result)
if type(result) in RESULT_WRAPPERS:
result = RESULT_WRAPPERS[type(result)](
result, render_result=render_result
)
# If the literal_eval result is a string, use the original
# render, by not returning right here. The evaluation of strings
# resulting in strings impacts quotes, to avoid unexpected
# output; use the original render instead of the evaluated one.
# Complex and scientific values are also unexpected. Filter them out.
if (
# Filter out string and complex numbers
not isinstance(result, (str, complex))
and (
# Pass if not numeric and not a boolean
not isinstance(result, (int, float))
# Or it's a boolean (inherit from int)
or isinstance(result, bool)
# Or if it's a digit
or _IS_NUMERIC.match(render_result) is not None
)
):
return result
return _cached_parse_result(render_result)
except (ValueError, TypeError, SyntaxError, MemoryError):
pass