(self, template, start='${', end='}$')
| 31 | auto_emit = re.compile('(^[\'\"])|(^[a-zA-Z0-9_\[\]\'\"]+$)') |
| 32 | |
| 33 | def __init__(self, template, start='${', end='}$'): |
| 34 | if len(start) != 2 or len(end) != 2: |
| 35 | raise ValueError('each delimiter must be two characters long') |
| 36 | delimiter = re.compile('%s(.*?)%s' % (re.escape(start), re.escape(end)), re.DOTALL) |
| 37 | offset = 0 |
| 38 | tokens = [] |
| 39 | for i, part in enumerate(delimiter.split(template)): |
| 40 | part = part.replace('\\'.join(list(start)), start) |
| 41 | part = part.replace('\\'.join(list(end)), end) |
| 42 | if i % 2 == 0: |
| 43 | if not part: continue |
| 44 | part = part.replace('\\', '\\\\').replace('"', '\\"') |
| 45 | part = '\t' * offset + 'emit("""%s""")' % part |
| 46 | else: |
| 47 | part = part.rstrip() |
| 48 | if not part: continue |
| 49 | if part.lstrip().startswith(':'): |
| 50 | if not offset: |
| 51 | raise SyntaxError('no block statement to terminate: ${%s}$' % part) |
| 52 | offset -= 1 |
| 53 | part = part.lstrip()[1:] |
| 54 | if not part.endswith(':'): continue |
| 55 | elif self.auto_emit.match(part.lstrip()): |
| 56 | part = 'emit(%s)' % part.lstrip() |
| 57 | lines = part.splitlines() |
| 58 | margin = min(len(l) - len(l.lstrip()) for l in lines if l.strip()) |
| 59 | part = '\n'.join('\t' * offset + l[margin:] for l in lines) |
| 60 | if part.endswith(':'): |
| 61 | offset += 1 |
| 62 | tokens.append(part) |
| 63 | if offset: |
| 64 | raise SyntaxError('%i block statement(s) not terminated' % offset) |
| 65 | self.__code = compile('\n'.join(tokens), '<templite %r>' % template[:20], 'exec') |
| 66 | |
| 67 | def render(self, __namespace=None, **kw): |
| 68 | """ |
nothing calls this directly
no test coverage detected