初始提交,未完全测试
This commit is contained in:
266
template/EngineConfig.py
Normal file
266
template/EngineConfig.py
Normal file
@@ -0,0 +1,266 @@
|
||||
#!/usr/bin/env python3.9
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
JFinal EngineConfig - Template Engine Configuration
|
||||
"""
|
||||
|
||||
from typing import Dict, Optional, List, Set, Type, Any
|
||||
from decimal import Decimal
|
||||
from .Directive import Directive
|
||||
from .stat.Parser import Parser
|
||||
from .stat.ast.Define import Define
|
||||
from .stat.OutputDirectiveFactory import OutputDirectiveFactory
|
||||
from .io.WriterBuffer import WriterBuffer
|
||||
from .source.ISourceFactory import ISourceFactory
|
||||
from .source.FileSourceFactory import FileSourceFactory
|
||||
from .expr.ast.SharedMethodKit import SharedMethodKit
|
||||
from .ext.directive.RenderDirective import RenderDirective
|
||||
from .ext.directive.DateDirective import DateDirective
|
||||
from .ext.directive.EscapeDirective import EscapeDirective
|
||||
from .ext.directive.RandomDirective import RandomDirective
|
||||
from .ext.directive.NumberDirective import NumberDirective
|
||||
from .ext.directive.CallDirective import CallDirective
|
||||
from .ext.directive.StringDirective import StringDirective
|
||||
from .ext.sharedmethod.SharedMethodLib import SharedMethodLib
|
||||
|
||||
class EngineConfig:
|
||||
"""Template engine configuration"""
|
||||
|
||||
DEFAULT_ENCODING = "UTF-8"
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize engine configuration"""
|
||||
self._writer_buffer = WriterBuffer()
|
||||
self._compressor = None
|
||||
self._shared_function_map: Dict[str, Define] = {}
|
||||
self._shared_function_source_list: List[object] = []
|
||||
self._shared_object_map: Optional[Dict[str, Any]] = None
|
||||
self._output_directive_factory = OutputDirectiveFactory()
|
||||
self._source_factory = FileSourceFactory()
|
||||
self._directive_map: Dict[str, Type[Directive]] = {}
|
||||
self._shared_method_kit = SharedMethodKit()
|
||||
self._keep_line_blank_directives: Set[str] = set()
|
||||
|
||||
self._dev_mode = False
|
||||
self._reload_modified_shared_function_in_dev_mode = True
|
||||
self._base_template_path: Optional[str] = None
|
||||
self._encoding = EngineConfig.DEFAULT_ENCODING
|
||||
self._date_pattern = "yyyy-MM-dd HH:mm"
|
||||
self._rounding_mode = "HALF_UP" # Default rounding mode
|
||||
self._support_static_method_expression = False
|
||||
self._support_static_field_expression = False
|
||||
|
||||
# Initialize built-in directives
|
||||
self._init_builtin_directives()
|
||||
|
||||
def _init_builtin_directives(self):
|
||||
"""Initialize built-in directives"""
|
||||
self._keep_line_blank_directives.add("output")
|
||||
self._keep_line_blank_directives.add("include")
|
||||
|
||||
self.add_directive("render", RenderDirective, True)
|
||||
self.add_directive("date", DateDirective, True)
|
||||
self.add_directive("escape", EscapeDirective, True)
|
||||
self.add_directive("random", RandomDirective, True)
|
||||
self.add_directive("number", NumberDirective, True)
|
||||
self.add_directive("call", CallDirective, False)
|
||||
self.add_directive("string", StringDirective, False)
|
||||
|
||||
# Add built-in shared methods
|
||||
self.add_shared_method(SharedMethodLib())
|
||||
|
||||
def add_shared_function(self, file_name: str):
|
||||
"""Add shared function from file"""
|
||||
file_name = file_name.replace("\\", "/")
|
||||
source = self._source_factory.get_source(self._base_template_path, file_name, self._encoding)
|
||||
self._do_add_shared_function(source, file_name)
|
||||
|
||||
def _do_add_shared_function(self, source, file_name: str):
|
||||
"""Internal method to add shared function"""
|
||||
# Create a minimal env for parsing
|
||||
env = Env(self)
|
||||
parser = Parser(env, source.get_content(), file_name)
|
||||
parser.parse()
|
||||
|
||||
# Add to shared function map
|
||||
func_map = env.get_function_map()
|
||||
for func_name, func in func_map.items():
|
||||
if func_name in self._shared_function_map:
|
||||
raise ValueError(f"Template function already exists: {func_name}")
|
||||
|
||||
self._shared_function_map[func_name] = func
|
||||
|
||||
# Add source for dev mode
|
||||
if self._dev_mode:
|
||||
self._shared_function_source_list.append(source)
|
||||
env.add_source(source)
|
||||
|
||||
def add_shared_function_by_content(self, content: str):
|
||||
"""Add shared function from content string"""
|
||||
from .source.StringSource import StringSource
|
||||
string_source = StringSource(content, False)
|
||||
self._do_add_shared_function(string_source, None)
|
||||
|
||||
def add_shared_object(self, name: str, obj: Any):
|
||||
"""Add shared object"""
|
||||
if self._shared_object_map is None:
|
||||
self._shared_object_map = {}
|
||||
|
||||
if name in self._shared_object_map:
|
||||
raise ValueError(f"Shared object already exists: {name}")
|
||||
|
||||
self._shared_object_map[name] = obj
|
||||
|
||||
def get_shared_object(self, name: str) -> Optional[Any]:
|
||||
"""Get shared object"""
|
||||
if self._shared_object_map:
|
||||
return self._shared_object_map.get(name)
|
||||
return None
|
||||
|
||||
def remove_shared_object(self, name: str):
|
||||
"""Remove shared object"""
|
||||
if self._shared_object_map:
|
||||
self._shared_object_map.pop(name, None)
|
||||
|
||||
def add_directive(self, directive_name: str, directive_class: Type[Directive], keep_line_blank: bool = False):
|
||||
"""Add custom directive"""
|
||||
if not directive_name or not directive_name.strip():
|
||||
raise ValueError("directive name cannot be blank")
|
||||
|
||||
if directive_class is None:
|
||||
raise ValueError("directiveClass cannot be null")
|
||||
|
||||
if directive_name in self._directive_map:
|
||||
raise ValueError(f"directive already exists: {directive_name}")
|
||||
|
||||
self._directive_map[directive_name] = directive_class
|
||||
|
||||
if keep_line_blank:
|
||||
self._keep_line_blank_directives.add(directive_name)
|
||||
|
||||
def get_directive(self, directive_name: str) -> Optional[Type[Directive]]:
|
||||
"""Get directive class"""
|
||||
return self._directive_map.get(directive_name)
|
||||
|
||||
def remove_directive(self, directive_name: str):
|
||||
"""Remove directive"""
|
||||
self._directive_map.pop(directive_name, None)
|
||||
self._keep_line_blank_directives.discard(directive_name)
|
||||
|
||||
def add_shared_method(self, obj: Any):
|
||||
"""Add shared method from object"""
|
||||
self._shared_method_kit.add_shared_method(obj)
|
||||
|
||||
def add_shared_method_from_class(self, clazz: Type):
|
||||
"""Add shared method from class"""
|
||||
self._shared_method_kit.add_shared_method(clazz)
|
||||
|
||||
def add_shared_static_method(self, clazz: Type):
|
||||
"""Add shared static method from class"""
|
||||
self._shared_method_kit.add_shared_static_method(clazz)
|
||||
|
||||
def remove_shared_method(self, method_name: str):
|
||||
"""Remove shared method by name"""
|
||||
self._shared_method_kit.remove_shared_method(method_name)
|
||||
|
||||
def get_shared_method_kit(self) -> SharedMethodKit:
|
||||
"""Get shared method kit"""
|
||||
return self._shared_method_kit
|
||||
|
||||
# Property accessors
|
||||
@property
|
||||
def dev_mode(self) -> bool:
|
||||
"""Get dev mode setting"""
|
||||
return self._dev_mode
|
||||
|
||||
@dev_mode.setter
|
||||
def dev_mode(self, value: bool):
|
||||
"""Set dev mode"""
|
||||
self._dev_mode = value
|
||||
|
||||
@property
|
||||
def base_template_path(self) -> Optional[str]:
|
||||
"""Get base template path"""
|
||||
return self._base_template_path
|
||||
|
||||
@base_template_path.setter
|
||||
def base_template_path(self, value: str):
|
||||
"""Set base template path"""
|
||||
if value is None:
|
||||
self._base_template_path = None
|
||||
return
|
||||
|
||||
value = value.strip().replace("\\", "/")
|
||||
if not value:
|
||||
raise ValueError("baseTemplatePath cannot be blank")
|
||||
|
||||
if len(value) > 1 and value.endswith("/"):
|
||||
value = value[:-1]
|
||||
|
||||
self._base_template_path = value
|
||||
|
||||
@property
|
||||
def encoding(self) -> str:
|
||||
"""Get encoding"""
|
||||
return self._encoding
|
||||
|
||||
@encoding.setter
|
||||
def encoding(self, value: str):
|
||||
"""Set encoding"""
|
||||
if not value:
|
||||
raise ValueError("encoding cannot be blank")
|
||||
self._encoding = value
|
||||
self._writer_buffer.set_encoding(value)
|
||||
|
||||
@property
|
||||
def date_pattern(self) -> str:
|
||||
"""Get date pattern"""
|
||||
return self._date_pattern
|
||||
|
||||
@date_pattern.setter
|
||||
def date_pattern(self, value: str):
|
||||
"""Set date pattern"""
|
||||
if not value:
|
||||
raise ValueError("datePattern cannot be blank")
|
||||
self._date_pattern = value
|
||||
|
||||
@property
|
||||
def rounding_mode(self) -> str:
|
||||
"""Get rounding mode"""
|
||||
return self._rounding_mode
|
||||
|
||||
@rounding_mode.setter
|
||||
def rounding_mode(self, value: str):
|
||||
"""Set rounding mode"""
|
||||
self._rounding_mode = value
|
||||
|
||||
@property
|
||||
def writer_buffer(self) -> WriterBuffer:
|
||||
"""Get writer buffer"""
|
||||
return self._writer_buffer
|
||||
|
||||
@property
|
||||
def source_factory(self) -> ISourceFactory:
|
||||
"""Get source factory"""
|
||||
return self._source_factory
|
||||
|
||||
@source_factory.setter
|
||||
def source_factory(self, value: ISourceFactory):
|
||||
"""Set source factory"""
|
||||
if value is None:
|
||||
raise ValueError("sourceFactory cannot be null")
|
||||
self._source_factory = value
|
||||
|
||||
@property
|
||||
def shared_function_map(self) -> Dict[str, Define]:
|
||||
"""Get shared function map"""
|
||||
return self._shared_function_map.copy()
|
||||
|
||||
@property
|
||||
def shared_object_map(self) -> Optional[Dict[str, Any]]:
|
||||
"""Get shared object map"""
|
||||
return self._shared_object_map.copy() if self._shared_object_map else None
|
||||
|
||||
|
||||
# Import needed classes to avoid circular imports
|
||||
from .Env import Env
|
||||
Reference in New Issue
Block a user