Flutter Engine
The Flutter Engine
templateloader.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2# Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
3# for details. All rights reserved. Use of this source code is governed by a
4# BSD-style license that can be found in the LICENSE file.
5
6# Template loader and preprocessor.
7#
8# Preprocessor language:
9#
10# //$ Comment line removed by preprocessor
11# $if VAR
12# $else
13# $endif
14#
15# VAR must be defined in the conditions dictionary.
16
17import os
18
19
20class TemplateLoader(object):
21 """Loads template files from a path."""
22
23 def __init__(self, root, subpaths, conditions={}):
24 """Initializes loader.
25
26 Args:
27 root - a string, the directory under which the templates are stored.
28 subpaths - a list of strings, subpaths of root in search order.
29 conditions - a dictionary from strings to booleans. Any conditional
30 expression must be a key in the map.
31 """
32 self._root = root
33 self._subpaths = subpaths
34 self._conditions = conditions
35 self._cache = {}
36
37 def TryLoad(self, name, more_conditions={}):
38 """Returns content of template file as a string, or None of not found."""
39 conditions = dict(self._conditions, **more_conditions)
40 cache_key = (name, tuple(sorted(conditions.items())))
41 if cache_key in self._cache:
42 return self._cache[cache_key]
43
44 for subpath in self._subpaths:
45 template_file = os.path.join(self._root, subpath, name)
46 if os.path.exists(template_file):
47 template = ''.join(open(template_file).readlines())
48 template = self._Preprocess(template, template_file, conditions)
49 self._cache[cache_key] = template
50 return template
51
52 return None
53
54 def Load(self, name, more_conditions={}):
55 """Returns contents of template file as a string, or raises an exception."""
56 template = self.TryLoad(name, more_conditions)
57 if template is not None: # Can be empty string
58 return template
59 raise Exception("Could not find template '%s' on %s / %s" %
60 (name, self._root, self._subpaths))
61
62 def _Preprocess(self, template, filename, conditions):
63
64 def error(lineno, message):
65 raise Exception('%s:%s: %s' % (filename, lineno, message))
66
67 lines = template.splitlines(True)
68 out = []
69
70 condition_stack = []
71 active = True
72 seen_else = False
73
74 for (lineno, full_line) in enumerate(lines):
75 line = full_line.strip()
76
77 if line.startswith('$'):
78 words = line.split()
79 directive = words[0]
80
81 if directive == '$if':
82 if len(words) != 2:
83 error(lineno, '$if does not have single variable')
84 variable = words[1]
85 if variable in conditions:
86 condition_stack.append((active, seen_else))
87 active = active and conditions[variable]
88 seen_else = False
89 else:
90 error(lineno, "Unknown $if variable '%s'" % variable)
91
92 elif directive == '$else':
93 if not condition_stack:
94 error(lineno, '$else without $if')
95 if seen_else:
96 raise error(lineno, 'Double $else')
97 seen_else = True
98 (parentactive,
99 _) = condition_stack[len(condition_stack) - 1]
100 active = not active and parentactive
101
102 elif directive == '$endif':
103 if not condition_stack:
104 error(lineno, '$endif without $if')
105 (active, seen_else) = condition_stack.pop()
106
107 else:
108 # Something else, like '$!MEMBERS'
109 if active:
110 out.append(full_line)
111 elif line.startswith('//$'):
112 pass # Ignore pre-processor comment.
113
114 else:
115 if active:
116 out.append(full_line)
117 continue
118
119 if condition_stack:
120 error(len(lines), 'Unterminated $if')
121
122 return ''.join(out)
def Load(self, name, more_conditions={})
def __init__(self, root, subpaths, conditions={})
def TryLoad(self, name, more_conditions={})
def _Preprocess(self, template, filename, conditions)
static void readlines(const void *data, size_t size, F f)
Definition: editor.cpp:30
const uint8_t uint32_t uint32_t GError ** error
static SkString join(const CommandLineFlags::StringArray &)
Definition: skpbench.cpp:741