##// END OF EJS Templates
formatter: verify number of arguments passed to write functions...
Yuya Nishihara -
r26372:55de8009 default
parent child Browse files
Show More
@@ -1,216 +1,220 b''
1 1 # formatter.py - generic output formatting for mercurial
2 2 #
3 3 # Copyright 2012 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import cPickle
11 11 import os
12 12
13 13 from .i18n import _
14 14 from .node import (
15 15 hex,
16 16 short,
17 17 )
18 18
19 19 from . import (
20 20 encoding,
21 21 templater,
22 22 util,
23 23 )
24 24
25 25 class baseformatter(object):
26 26 def __init__(self, ui, topic, opts):
27 27 self._ui = ui
28 28 self._topic = topic
29 29 self._style = opts.get("style")
30 30 self._template = opts.get("template")
31 31 self._item = None
32 32 # function to convert node to string suitable for this output
33 33 self.hexfunc = hex
34 34 def __nonzero__(self):
35 35 '''return False if we're not doing real templating so we can
36 36 skip extra work'''
37 37 return True
38 38 def _showitem(self):
39 39 '''show a formatted item once all data is collected'''
40 40 pass
41 41 def startitem(self):
42 42 '''begin an item in the format list'''
43 43 if self._item is not None:
44 44 self._showitem()
45 45 self._item = {}
46 46 def data(self, **data):
47 47 '''insert data into item that's not shown in default output'''
48 48 self._item.update(data)
49 49 def write(self, fields, deftext, *fielddata, **opts):
50 50 '''do default text output while assigning data to item'''
51 for k, v in zip(fields.split(), fielddata):
51 fieldkeys = fields.split()
52 assert len(fieldkeys) == len(fielddata)
53 for k, v in zip(fieldkeys, fielddata):
52 54 self._item[k] = v
53 55 def condwrite(self, cond, fields, deftext, *fielddata, **opts):
54 56 '''do conditional write (primarily for plain formatter)'''
55 for k, v in zip(fields.split(), fielddata):
57 fieldkeys = fields.split()
58 assert len(fieldkeys) == len(fielddata)
59 for k, v in zip(fieldkeys, fielddata):
56 60 self._item[k] = v
57 61 def plain(self, text, **opts):
58 62 '''show raw text for non-templated mode'''
59 63 pass
60 64 def end(self):
61 65 '''end output for the formatter'''
62 66 if self._item is not None:
63 67 self._showitem()
64 68
65 69 class plainformatter(baseformatter):
66 70 '''the default text output scheme'''
67 71 def __init__(self, ui, topic, opts):
68 72 baseformatter.__init__(self, ui, topic, opts)
69 73 if ui.debugflag:
70 74 self.hexfunc = hex
71 75 else:
72 76 self.hexfunc = short
73 77 def __nonzero__(self):
74 78 return False
75 79 def startitem(self):
76 80 pass
77 81 def data(self, **data):
78 82 pass
79 83 def write(self, fields, deftext, *fielddata, **opts):
80 84 self._ui.write(deftext % fielddata, **opts)
81 85 def condwrite(self, cond, fields, deftext, *fielddata, **opts):
82 86 '''do conditional write'''
83 87 if cond:
84 88 self._ui.write(deftext % fielddata, **opts)
85 89 def plain(self, text, **opts):
86 90 self._ui.write(text, **opts)
87 91 def end(self):
88 92 pass
89 93
90 94 class debugformatter(baseformatter):
91 95 def __init__(self, ui, topic, opts):
92 96 baseformatter.__init__(self, ui, topic, opts)
93 97 self._ui.write("%s = [\n" % self._topic)
94 98 def _showitem(self):
95 99 self._ui.write(" " + repr(self._item) + ",\n")
96 100 def end(self):
97 101 baseformatter.end(self)
98 102 self._ui.write("]\n")
99 103
100 104 class pickleformatter(baseformatter):
101 105 def __init__(self, ui, topic, opts):
102 106 baseformatter.__init__(self, ui, topic, opts)
103 107 self._data = []
104 108 def _showitem(self):
105 109 self._data.append(self._item)
106 110 def end(self):
107 111 baseformatter.end(self)
108 112 self._ui.write(cPickle.dumps(self._data))
109 113
110 114 def _jsonifyobj(v):
111 115 if isinstance(v, tuple):
112 116 return '[' + ', '.join(_jsonifyobj(e) for e in v) + ']'
113 117 elif v is None:
114 118 return 'null'
115 119 elif v is True:
116 120 return 'true'
117 121 elif v is False:
118 122 return 'false'
119 123 elif isinstance(v, (int, float)):
120 124 return str(v)
121 125 else:
122 126 return '"%s"' % encoding.jsonescape(v)
123 127
124 128 class jsonformatter(baseformatter):
125 129 def __init__(self, ui, topic, opts):
126 130 baseformatter.__init__(self, ui, topic, opts)
127 131 self._ui.write("[")
128 132 self._ui._first = True
129 133 def _showitem(self):
130 134 if self._ui._first:
131 135 self._ui._first = False
132 136 else:
133 137 self._ui.write(",")
134 138
135 139 self._ui.write("\n {\n")
136 140 first = True
137 141 for k, v in sorted(self._item.items()):
138 142 if first:
139 143 first = False
140 144 else:
141 145 self._ui.write(",\n")
142 146 self._ui.write(' "%s": %s' % (k, _jsonifyobj(v)))
143 147 self._ui.write("\n }")
144 148 def end(self):
145 149 baseformatter.end(self)
146 150 self._ui.write("\n]\n")
147 151
148 152 class templateformatter(baseformatter):
149 153 def __init__(self, ui, topic, opts):
150 154 baseformatter.__init__(self, ui, topic, opts)
151 155 self._topic = topic
152 156 self._t = gettemplater(ui, topic, opts.get('template', ''))
153 157 def _showitem(self):
154 158 g = self._t(self._topic, **self._item)
155 159 self._ui.write(templater.stringify(g))
156 160
157 161 def lookuptemplate(ui, topic, tmpl):
158 162 # looks like a literal template?
159 163 if '{' in tmpl:
160 164 return tmpl, None
161 165
162 166 # perhaps a stock style?
163 167 if not os.path.split(tmpl)[0]:
164 168 mapname = (templater.templatepath('map-cmdline.' + tmpl)
165 169 or templater.templatepath(tmpl))
166 170 if mapname and os.path.isfile(mapname):
167 171 return None, mapname
168 172
169 173 # perhaps it's a reference to [templates]
170 174 t = ui.config('templates', tmpl)
171 175 if t:
172 176 try:
173 177 tmpl = templater.unquotestring(t)
174 178 except SyntaxError:
175 179 tmpl = t
176 180 return tmpl, None
177 181
178 182 if tmpl == 'list':
179 183 ui.write(_("available styles: %s\n") % templater.stylelist())
180 184 raise util.Abort(_("specify a template"))
181 185
182 186 # perhaps it's a path to a map or a template
183 187 if ('/' in tmpl or '\\' in tmpl) and os.path.isfile(tmpl):
184 188 # is it a mapfile for a style?
185 189 if os.path.basename(tmpl).startswith("map-"):
186 190 return None, os.path.realpath(tmpl)
187 191 tmpl = open(tmpl).read()
188 192 return tmpl, None
189 193
190 194 # constant string?
191 195 return tmpl, None
192 196
193 197 def gettemplater(ui, topic, spec):
194 198 tmpl, mapfile = lookuptemplate(ui, topic, spec)
195 199 t = templater.templater(mapfile, {})
196 200 if tmpl:
197 201 t.cache[topic] = tmpl
198 202 return t
199 203
200 204 def formatter(ui, topic, opts):
201 205 template = opts.get("template", "")
202 206 if template == "json":
203 207 return jsonformatter(ui, topic, opts)
204 208 elif template == "pickle":
205 209 return pickleformatter(ui, topic, opts)
206 210 elif template == "debug":
207 211 return debugformatter(ui, topic, opts)
208 212 elif template != "":
209 213 return templateformatter(ui, topic, opts)
210 214 # developer config: ui.formatdebug
211 215 elif ui.configbool('ui', 'formatdebug'):
212 216 return debugformatter(ui, topic, opts)
213 217 # deprecated config: ui.formatjson
214 218 elif ui.configbool('ui', 'formatjson'):
215 219 return jsonformatter(ui, topic, opts)
216 220 return plainformatter(ui, topic, opts)
General Comments 0
You need to be logged in to leave comments. Login now