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
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-17 01:37 +0200
1"""CX text-only templates.
3This template is based on Jump, like html templates,
4but doesn't support custom commands and non-text outputs.
5"""
7from typing import Optional
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
19gws.ext.new.template('text')
22class Config(gws.base.template.Config):
23 """Text-only template. (added in 8.1)"""
25 path: Optional[gws.FilePath]
26 """Path to a template file."""
27 text: str = ''
28 """Template content."""
31class Props(gws.base.template.Props):
32 pass
35class Object(gws.base.template.Object):
36 path: str
37 text: str
38 compiledTime: float = 0
39 compiledFn = None
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')
47 def render(self, tri):
48 self.notify(tri, 'begin_print')
50 engine = Engine()
51 self.compile(engine)
53 args = self.prepare_args(tri)
54 res = engine.call(self.compiledFn, args=args, error=self.error_handler)
56 if not isinstance(res, gws.Response):
57 res = self.finalize(tri, res, args, engine)
59 self.notify(tri, 'end_print')
60 return res
62 def compile(self, engine: 'Engine'):
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
68 if self.root.app.developer_option('template.always_reload'):
69 self.compiledFn = None
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 )
79 self.compiledFn = engine.compile(self.text, path=self.path)
80 self.compiledTime = gws.u.utime()
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
90 gws.log.warning(f'TEMPLATE_ERROR: {self}: {exc} IN {path}:{line}')
91 return True
93 ##
95 def finalize(self, tri: gws.TemplateRenderInput, res: str, args: dict, main_engine: 'Engine'):
96 self.notify(tri, 'finalize_print')
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
104 return gws.ContentResponse(mime=mime, content=res)
107##
110class Engine(gws.lib.vendor.jump.Engine):
111 pass