Coverage for jinja2_async_environment/compiler_modules/patterns.py: 100%

1"""Pre-compiled regex patterns for template compilation optimization."""

2

3 import re

4

5

6 class CompiledPatterns:

7 """Pre-compiled regex patterns for template compilation optimization."""

8

9 # Pattern for async yield detection

10 ASYNC_YIELD_PATTERN = re.compile(

11 r"async for event in self\._async_yield_from\([^)]+\):\s*$", re.MULTILINE

12 )

13

14 # Pattern for undefined variable detection

15 UNDEFINED_VAR_PATTERN = re.compile(

16 r"undefined\(name='([^']+)'\) if l_0_\1 is missing else l_0_\1"

17 )

18

19 # Pattern for loop variable optimization

20 LOOP_VAR_PATTERN = re.compile(r"l_0_(\w+)")

21

22 # Pattern for context block detection

23 CONTEXT_BLOCK_PATTERN = re.compile(r"yield from context\.blocks")

24

25 # Additional performance patterns

26 HASATTR_CHECK_PATTERN = re.compile(r"hasattr\(([^,]+),\s*'__await__'\)")

27 AUTO_AITER_PATTERN = re.compile(r"auto_aiter\(([^)]+)\)")

28 TEMPLATE_RUNTIME_ERROR_PATTERN = re.compile(r'TemplateRuntimeError\("([^"]+)"\)')

29 DUPLICATE_IMPORT_PATTERN = re.compile(r"^from ([\w.]+) import (.+)$", re.MULTILINE)

30 REDUNDANT_ESCAPE_PATTERN = re.compile(r"escape\(escape\(([^)]+)\)\)")

31 CONSTANT_UNDEFINED_PATTERN = re.compile(r"undefined\(name=None\)")

32

33 # Cached import statements for faster code generation

34 _CACHED_IMPORTS = {

35 "runtime": "from jinja2.runtime import Undefined, Macro, missing, LoopContext, AsyncLoopContext, auto_aiter, Namespace, TemplateRuntimeError",

36 "markupsafe": "from markupsafe import escape",

37 "defaults": "from jinja2.defaults import DEFAULT_FILTERS",

38 }

39

40 @classmethod

41 def get_optimized_imports(cls) -> str:

42 """Return optimized import statements as a single string."""

43 return "\n".join(cls._CACHED_IMPORTS.values())

44

45 @classmethod

46 def optimize_generated_code(cls, code: str) -> str:

47 """Apply pattern-based optimizations to generated template code."""

48 optimized_code = code

49

50 # Fast string replacements for common patterns

51 optimizations = [

52 ("yield from context.blocks", "pass # yield from replaced"),

53 ("undefined(name='item') if l_0_item is missing else l_0_item", "item"),

54 ("undefined(name=None)", "Undefined()"),

55 ("escape(escape(", "escape("), # Remove double escaping

56 (

57 "if hasattr(value, '__await__'):\n return await value\nelse:\n return value",

58 "return await value if hasattr(value, '__await__') else value",

59 ),

60 ]

61

62 for pattern, replacement in optimizations:

63 optimized_code = optimized_code.replace(pattern, replacement)

64

65 # Use regex patterns for more complex optimizations

66 optimized_code = cls._optimize_with_regex(optimized_code)

67

68 # Remove duplicate imports

69 optimized_code = cls._deduplicate_imports(optimized_code)

70

71 return optimized_code

72

73 @classmethod

74 def _optimize_with_regex(cls, code: str) -> str:

75 """Apply regex-based optimizations."""

76

77 # Optimize hasattr checks

78 def optimize_hasattr(match):

79 var = match.group(1)

80 return f"getattr({var}, '__await__', None) is not None"

81

82 code = cls.HASATTR_CHECK_PATTERN.sub(optimize_hasattr, code)

83

84 # Remove redundant escape calls

85 code = cls.REDUNDANT_ESCAPE_PATTERN.sub(r"escape(\1)", code)

86

87 return code

88

89 @classmethod

90 def _deduplicate_imports(cls, code: str) -> str:

91 """Remove duplicate import statements."""

92 lines = code.split("\n")

93 seen_imports = set()

94 deduplicated_lines = []

95

96 for line in lines:

97 if line.strip().startswith("from ") and " import " in line:

98 if line not in seen_imports:

99 seen_imports.add(line)

100 deduplicated_lines.append(line)

101 else:

102 deduplicated_lines.append(line)

103

104 return "\n".join(deduplicated_lines)