Mercurial > genshi > mirror
annotate genshi/template/interpolation.py @ 425:073640758a42 trunk
Try to use proper reStructuredText for docstrings throughout.
author | cmlenz |
---|---|
date | Thu, 22 Mar 2007 12:45:18 +0000 |
parents | 5d08a744636e |
children | 97544725bb7f |
rev | line source |
---|---|
407
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
1 # -*- coding: utf-8 -*- |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
2 # |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
3 # Copyright (C) 2007 Edgewall Software |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
4 # All rights reserved. |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
5 # |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
6 # This software is licensed as described in the file COPYING, which |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
7 # you should have received as part of this distribution. The terms |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
8 # are also available at http://genshi.edgewall.org/wiki/License. |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
9 # |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
10 # This software consists of voluntary contributions made by many |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
11 # individuals. For the exact contribution history, see the revision |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
12 # history and logs, available at http://genshi.edgewall.org/log/. |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
13 |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
14 """String interpolation routines, i.e. the splitting up a given text into some |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
15 parts that are literal strings, and others that are Python expressions. |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
16 """ |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
17 |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
18 from itertools import chain |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
19 import os |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
20 from tokenize import tokenprog |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
21 |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
22 from genshi.core import TEXT |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
23 from genshi.template.base import TemplateSyntaxError, EXPR |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
24 from genshi.template.eval import Expression |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
25 |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
26 __all__ = ['interpolate'] |
425
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
27 __docformat__ = 'restructuredtext en' |
407
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
28 |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
29 NAMESTART = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_' |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
30 NAMECHARS = NAMESTART + '.0123456789' |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
31 PREFIX = '$' |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
32 |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
33 def interpolate(text, basedir=None, filename=None, lineno=-1, offset=0): |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
34 """Parse the given string and extract expressions. |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
35 |
425
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
36 This function is a generator that yields `TEXT` events for literal strings, |
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
37 and `EXPR` events for expressions, depending on the results of parsing the |
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
38 string. |
407
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
39 |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
40 >>> for kind, data, pos in interpolate("$foo bar"): |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
41 ... print kind, `data` |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
42 EXPR Expression('foo') |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
43 TEXT u' bar' |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
44 |
425
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
45 :param text: the text to parse |
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
46 :param basedir: base directory of the file in which the text was found |
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
47 (optional) |
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
48 :param filename: basename of the file in which the text was found (optional) |
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
49 :param lineno: the line number at which the text was found (optional) |
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
50 :param offset: the column number at which the text starts in the source |
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
51 (optional) |
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
52 :return: a list of `TEXT` and `EXPR` events |
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
53 :raise TemplateSyntaxError: when a syntax error in an expression is |
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
54 encountered |
407
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
55 """ |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
56 filepath = filename |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
57 if filepath and basedir: |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
58 filepath = os.path.join(basedir, filepath) |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
59 pos = [filepath, lineno, offset] |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
60 |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
61 textbuf = [] |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
62 textpos = None |
422
5d08a744636e
More work to include absolute file paths in exceptions.
cmlenz
parents:
407
diff
changeset
|
63 for is_expr, chunk in chain(lex(text, pos, filepath), [(True, '')]): |
407
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
64 if is_expr: |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
65 if textbuf: |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
66 yield TEXT, u''.join(textbuf), textpos |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
67 del textbuf[:] |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
68 textpos = None |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
69 if chunk: |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
70 try: |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
71 expr = Expression(chunk.strip(), pos[0], pos[1]) |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
72 yield EXPR, expr, tuple(pos) |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
73 except SyntaxError, err: |
422
5d08a744636e
More work to include absolute file paths in exceptions.
cmlenz
parents:
407
diff
changeset
|
74 raise TemplateSyntaxError(err, filepath, pos[1], |
407
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
75 pos[2] + (err.offset or 0)) |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
76 else: |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
77 textbuf.append(chunk) |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
78 if textpos is None: |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
79 textpos = tuple(pos) |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
80 |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
81 if '\n' in chunk: |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
82 lines = chunk.splitlines() |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
83 pos[1] += len(lines) - 1 |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
84 pos[2] += len(lines[-1]) |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
85 else: |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
86 pos[2] += len(chunk) |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
87 |
422
5d08a744636e
More work to include absolute file paths in exceptions.
cmlenz
parents:
407
diff
changeset
|
88 def lex(text, textpos, filepath): |
407
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
89 offset = pos = 0 |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
90 end = len(text) |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
91 escaped = False |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
92 |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
93 while 1: |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
94 if escaped: |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
95 offset = text.find(PREFIX, offset + 2) |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
96 escaped = False |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
97 else: |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
98 offset = text.find(PREFIX, pos) |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
99 if offset < 0 or offset == end - 1: |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
100 break |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
101 next = text[offset + 1] |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
102 |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
103 if next == '{': |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
104 if offset > pos: |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
105 yield False, text[pos:offset] |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
106 pos = offset + 2 |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
107 level = 1 |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
108 while level: |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
109 match = tokenprog.match(text, pos) |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
110 if match is None: |
422
5d08a744636e
More work to include absolute file paths in exceptions.
cmlenz
parents:
407
diff
changeset
|
111 raise TemplateSyntaxError('invalid syntax', filepath, |
5d08a744636e
More work to include absolute file paths in exceptions.
cmlenz
parents:
407
diff
changeset
|
112 *textpos[1:]) |
407
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
113 pos = match.end() |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
114 tstart, tend = match.regs[3] |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
115 token = text[tstart:tend] |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
116 if token == '{': |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
117 level += 1 |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
118 elif token == '}': |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
119 level -= 1 |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
120 yield True, text[offset + 2:pos - 1] |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
121 |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
122 elif next in NAMESTART: |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
123 if offset > pos: |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
124 yield False, text[pos:offset] |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
125 pos = offset |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
126 pos += 1 |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
127 while pos < end: |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
128 char = text[pos] |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
129 if char not in NAMECHARS: |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
130 break |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
131 pos += 1 |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
132 yield True, text[offset + 1:pos].strip() |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
133 |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
134 elif not escaped and next == PREFIX: |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
135 escaped = True |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
136 pos = offset + 1 |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
137 |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
138 else: |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
139 yield False, text[pos:offset + 1] |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
140 pos = offset + 1 |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
141 |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
142 if pos < end: |
f37d8e6acdf2
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
diff
changeset
|
143 yield False, text[pos:] |