inji.engine.TemplateEngine.render()   A
last analyzed

Complexity

Conditions 2

Size

Total Lines 28
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 16
dl 0
loc 28
ccs 12
cts 12
cp 1
rs 9.6
c 0
b 0
f 0
cc 2
nop 3
crap 2
1
#!/usr/bin/env python3
2
3
# -*- coding: utf-8 -*-
4
5 1
from jinja2 import DebugUndefined, StrictUndefined, Undefined, make_logging_undefined
6 1
from jinja2 import Environment, FileSystemLoader
7 1
from jinja2.exceptions import TemplateNotFound, UndefinedError
8 1
import sys
9 1
import logging
10 1
import inspect
11
12 1
from . import utils
13 1
from . import filters
14 1
from . import tests
15 1
from . import globals
16
17 1
def get_symbols(mod):
18 1
  return { k:v for k,v
19
            in inspect.getmembers(mod)
20
            if not (k.startswith('_')) }
21
22 1
class TemplateEngine(object):
23
24 1
  def __init__( self,
25
                undefined_variables_mode_behaviour='strict',
26
                j2_env_params={},
27
    ):
28
29 1
    UndefinedHandler = StrictUndefined
30 1
    m = undefined_variables_mode_behaviour
31 1
    if   m in ['empty',  'Undefined']:
32 1
      UndefinedHandler = Undefined
33 1
    elif m in ['keep',   'DebugUndefined']:
34 1
      UndefinedHandler = DebugUndefined
35
36
    # Setup debug logging on STDERR to have the jinja2 engine emit
37
    # its activities
38 1
    root = logging.getLogger(__name__)
39 1
    root.setLevel(logging.DEBUG)
40 1
    handler = logging.StreamHandler(sys.stderr)
41 1
    handler.setFormatter(logging.Formatter('%(name)s %(levelname)s: %(message)s'))
42 1
    root.addHandler(handler)
43
44 1
    UndefinedHandler = make_logging_undefined( logger=root, base=UndefinedHandler )
45
46 1
    j2_env_params.setdefault('undefined', UndefinedHandler)
47 1
    j2_env_params.setdefault('trim_blocks', True)
48 1
    j2_env_params.setdefault('keep_trailing_newline', False)
49 1
    j2_env_params.setdefault('extensions', [
50
                            'jinja2.ext.i18n',
51
                            'jinja2.ext.do',
52
                            'jinja2.ext.loopcontrols',
53
                          ])
54
55 1
    self.j2_env_params = j2_env_params
56
57 1
    self.filters = get_symbols(filters)
58 1
    self.tests   = get_symbols(tests)
59 1
    self.globals = get_symbols(globals)
60
61 1
  def render(
62
      self,
63
      template,
64
      context
65
    ):
66
    """ Render the template """
67
68
    # We don't assume that includes and other sourceables reside relative
69
    # to the current directory but instead relative to the "master" template
70
    # we are processing. We deviate from jinja tradition this way.
71
    # This is because.
72
    # 1. We process template from stdin in temporary directories
73
    # 2. We should be free to change the process CWD and not break rendering
74 1
    rootdir = utils.dirname(template)
75
76 1
    self.j2_env_params.setdefault('loader', FileSystemLoader(rootdir))
77 1
    j2_env = Environment(**self.j2_env_params)
78
79 1
    j2_env.globals.update(self.globals)
80 1
    j2_env.filters.update(self.filters)
81 1
    j2_env.tests.update(self.tests)
82
83 1
    try:
84 1
      template = utils.basename(template)
85 1
      yield j2_env.get_template(template).render(context)
86 1
    except UndefinedError as e:
87 1
      raise UndefinedError( "variable {} in template '{}'".format(
88
              str(e), template) ) from e
89
90