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