Coverage for gws-app/gws/plugin/template/text/__init__.py: 0%

69 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-04-17 01:37 +0200

1"""CX text-only templates. 

2 

3This template is based on Jump, like html templates, 

4but doesn't support custom commands and non-text outputs. 

5""" 

6 

7from typing import Optional 

8 

9import gws 

10import gws.base.legend 

11import gws.base.template 

12import gws.gis.render 

13import gws.lib.htmlx 

14import gws.lib.mime 

15import gws.lib.osx 

16import gws.lib.pdf 

17import gws.lib.vendor.jump 

18 

19gws.ext.new.template('text') 

20 

21 

22class Config(gws.base.template.Config): 

23 """Text-only template. (added in 8.1)""" 

24 

25 path: Optional[gws.FilePath] 

26 """Path to a template file.""" 

27 text: str = '' 

28 """Template content.""" 

29 

30 

31class Props(gws.base.template.Props): 

32 pass 

33 

34 

35class Object(gws.base.template.Object): 

36 path: str 

37 text: str 

38 compiledTime: float = 0 

39 compiledFn = None 

40 

41 def configure(self): 

42 self.path = self.cfg('path') 

43 self.text = self.cfg('text', default='') 

44 if not self.path and not self.text: 

45 raise gws.Error('either "path" or "text" required') 

46 

47 def render(self, tri): 

48 self.notify(tri, 'begin_print') 

49 

50 engine = Engine() 

51 self.compile(engine) 

52 

53 args = self.prepare_args(tri) 

54 res = engine.call(self.compiledFn, args=args, error=self.error_handler) 

55 

56 if not isinstance(res, gws.Response): 

57 res = self.finalize(tri, res, args, engine) 

58 

59 self.notify(tri, 'end_print') 

60 return res 

61 

62 def compile(self, engine: 'Engine'): 

63 

64 if self.path and (not self.text or gws.lib.osx.file_mtime(self.path) > self.compiledTime): 

65 self.text = gws.u.read_file(self.path) 

66 self.compiledFn = None 

67 

68 if self.root.app.developer_option('template.always_reload'): 

69 self.compiledFn = None 

70 

71 if not self.compiledFn: 

72 gws.log.debug(f'compiling {self} {self.path=}') 

73 if self.root.app.developer_option('template.save_compiled'): 

74 gws.u.write_file( 

75 gws.u.ensure_dir(f'{gws.c.VAR_DIR}/debug') + f'/compiled_template_{self.uid}', 

76 engine.translate(self.text, path=self.path) 

77 ) 

78 

79 self.compiledFn = engine.compile(self.text, path=self.path) 

80 self.compiledTime = gws.u.utime() 

81 

82 def error_handler(self, exc, path, line, env): 

83 if self.root.app.developer_option('template.raise_errors'): 

84 gws.log.error(f'TEMPLATE_ERROR: {self}: {exc} IN {path}:{line}') 

85 for k, v in sorted(getattr(env, 'ARGS', {}).items()): 

86 gws.log.error(f'TEMPLATE_ERROR: {self}: ARGS {k}={v!r}') 

87 gws.log.error(f'TEMPLATE_ERROR: {self}: stop') 

88 return False 

89 

90 gws.log.warning(f'TEMPLATE_ERROR: {self}: {exc} IN {path}:{line}') 

91 return True 

92 

93 ## 

94 

95 def finalize(self, tri: gws.TemplateRenderInput, res: str, args: dict, main_engine: 'Engine'): 

96 self.notify(tri, 'finalize_print') 

97 

98 mime = tri.mimeOut 

99 if not mime and self.mimeTypes: 

100 mime = self.mimeTypes[0] 

101 if not mime: 

102 mime = gws.lib.mime.TXT 

103 

104 return gws.ContentResponse(mime=mime, content=res) 

105 

106 

107## 

108 

109 

110class Engine(gws.lib.vendor.jump.Engine): 

111 pass