##// END OF EJS Templates
exthelper: update the examples to be python3 complaint...
Matt Harbison -
r46544:bd22900e default
parent child Browse files
Show More
@@ -1,311 +1,311 b''
1 1 # Copyright 2012 Logilab SA <contact@logilab.fr>
2 2 # Pierre-Yves David <pierre-yves.david@ens-lyon.org>
3 3 # Octobus <contact@octobus.net>
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 #####################################################################
9 9 ### Extension helper ###
10 10 #####################################################################
11 11
12 12 from __future__ import absolute_import
13 13
14 14 from . import (
15 15 commands,
16 16 error,
17 17 extensions,
18 18 pycompat,
19 19 registrar,
20 20 )
21 21
22 22 from hgdemandimport import tracing
23 23
24 24
25 25 class exthelper(object):
26 26 """Helper for modular extension setup
27 27
28 28 A single helper should be instantiated for each module of an
29 29 extension, where a command or function needs to be wrapped, or a
30 30 command, extension hook, fileset, revset or template needs to be
31 31 registered. Helper methods are then used as decorators for
32 32 these various purposes. If an extension spans multiple modules,
33 33 all helper instances should be merged in the main module.
34 34
35 35 All decorators return the original function and may be chained.
36 36
37 37 Aside from the helper functions with examples below, several
38 38 registrar method aliases are available for adding commands,
39 39 configitems, filesets, revsets, and templates. Simply decorate
40 40 the appropriate methods, and assign the corresponding exthelper
41 41 variable to a module level variable of the extension. The
42 42 extension loading mechanism will handle the rest.
43 43
44 44 example::
45 45
46 46 # ext.py
47 47 eh = exthelper.exthelper()
48 48
49 49 # As needed:
50 50 cmdtable = eh.cmdtable
51 51 configtable = eh.configtable
52 52 filesetpredicate = eh.filesetpredicate
53 53 revsetpredicate = eh.revsetpredicate
54 54 templatekeyword = eh.templatekeyword
55 55
56 @eh.command('mynewcommand',
57 [('r', 'rev', [], _('operate on these revisions'))],
58 _('-r REV...'),
56 @eh.command(b'mynewcommand',
57 [(b'r', b'rev', [], _(b'operate on these revisions'))],
58 _(b'-r REV...'),
59 59 helpcategory=command.CATEGORY_XXX)
60 60 def newcommand(ui, repo, *revs, **opts):
61 61 # implementation goes here
62 62
63 eh.configitem('experimental', 'foo',
63 eh.configitem(b'experimental', b'foo',
64 64 default=False,
65 65 )
66 66
67 @eh.filesetpredicate('lfs()')
67 @eh.filesetpredicate(b'lfs()')
68 68 def filesetbabar(mctx, x):
69 69 return mctx.predicate(...)
70 70
71 @eh.revsetpredicate('hidden')
71 @eh.revsetpredicate(b'hidden')
72 72 def revsetbabar(repo, subset, x):
73 args = revset.getargs(x, 0, 0, 'babar accept no argument')
74 return [r for r in subset if 'babar' in repo[r].description()]
73 args = revset.getargs(x, 0, 0, b'babar accept no argument')
74 return [r for r in subset if b'babar' in repo[r].description()]
75 75
76 @eh.templatekeyword('babar')
76 @eh.templatekeyword(b'babar')
77 77 def kwbabar(ctx):
78 return 'babar'
78 return b'babar'
79 79 """
80 80
81 81 def __init__(self):
82 82 self._uipopulatecallables = []
83 83 self._uicallables = []
84 84 self._extcallables = []
85 85 self._repocallables = []
86 86 self._commandwrappers = []
87 87 self._extcommandwrappers = []
88 88 self._functionwrappers = []
89 89 self.cmdtable = {}
90 90 self.command = registrar.command(self.cmdtable)
91 91 self.configtable = {}
92 92 self.configitem = registrar.configitem(self.configtable)
93 93 self.filesetpredicate = registrar.filesetpredicate()
94 94 self.revsetpredicate = registrar.revsetpredicate()
95 95 self.templatekeyword = registrar.templatekeyword()
96 96
97 97 def merge(self, other):
98 98 self._uicallables.extend(other._uicallables)
99 99 self._uipopulatecallables.extend(other._uipopulatecallables)
100 100 self._extcallables.extend(other._extcallables)
101 101 self._repocallables.extend(other._repocallables)
102 102 self.filesetpredicate._merge(other.filesetpredicate)
103 103 self.revsetpredicate._merge(other.revsetpredicate)
104 104 self.templatekeyword._merge(other.templatekeyword)
105 105 self._commandwrappers.extend(other._commandwrappers)
106 106 self._extcommandwrappers.extend(other._extcommandwrappers)
107 107 self._functionwrappers.extend(other._functionwrappers)
108 108 self.cmdtable.update(other.cmdtable)
109 109 for section, items in pycompat.iteritems(other.configtable):
110 110 if section in self.configtable:
111 111 self.configtable[section].update(items)
112 112 else:
113 113 self.configtable[section] = items
114 114
115 115 def finaluisetup(self, ui):
116 116 """Method to be used as the extension uisetup
117 117
118 118 The following operations belong here:
119 119
120 120 - Changes to ui.__class__ . The ui object that will be used to run the
121 121 command has not yet been created. Changes made here will affect ui
122 122 objects created after this, and in particular the ui that will be
123 123 passed to runcommand
124 124 - Command wraps (extensions.wrapcommand)
125 125 - Changes that need to be visible to other extensions: because
126 126 initialization occurs in phases (all extensions run uisetup, then all
127 127 run extsetup), a change made here will be visible to other extensions
128 128 during extsetup
129 129 - Monkeypatch or wrap function (extensions.wrapfunction) of dispatch
130 130 module members
131 131 - Setup of pre-* and post-* hooks
132 132 - pushkey setup
133 133 """
134 134 for command, wrapper, opts in self._commandwrappers:
135 135 entry = extensions.wrapcommand(commands.table, command, wrapper)
136 136 if opts:
137 137 for opt in opts:
138 138 entry[1].append(opt)
139 139 for cont, funcname, wrapper in self._functionwrappers:
140 140 extensions.wrapfunction(cont, funcname, wrapper)
141 141 for c in self._uicallables:
142 142 with tracing.log('finaluisetup: %s', repr(c)):
143 143 c(ui)
144 144
145 145 def finaluipopulate(self, ui):
146 146 """Method to be used as the extension uipopulate
147 147
148 148 This is called once per ui instance to:
149 149
150 150 - Set up additional ui members
151 151 - Update configuration by ``ui.setconfig()``
152 152 - Extend the class dynamically
153 153 """
154 154 for c in self._uipopulatecallables:
155 155 c(ui)
156 156
157 157 def finalextsetup(self, ui):
158 158 """Method to be used as a the extension extsetup
159 159
160 160 The following operations belong here:
161 161
162 162 - Changes depending on the status of other extensions. (if
163 extensions.find('mq'))
163 extensions.find(b'mq'))
164 164 - Add a global option to all commands
165 165 """
166 166 knownexts = {}
167 167
168 168 for ext, command, wrapper, opts in self._extcommandwrappers:
169 169 if ext not in knownexts:
170 170 try:
171 171 e = extensions.find(ext)
172 172 except KeyError:
173 173 # Extension isn't enabled, so don't bother trying to wrap
174 174 # it.
175 175 continue
176 176 knownexts[ext] = e.cmdtable
177 177 entry = extensions.wrapcommand(knownexts[ext], command, wrapper)
178 178 if opts:
179 179 for opt in opts:
180 180 entry[1].append(opt)
181 181
182 182 for c in self._extcallables:
183 183 with tracing.log('finalextsetup: %s', repr(c)):
184 184 c(ui)
185 185
186 186 def finalreposetup(self, ui, repo):
187 187 """Method to be used as the extension reposetup
188 188
189 189 The following operations belong here:
190 190
191 191 - All hooks but pre-* and post-*
192 192 - Modify configuration variables
193 193 - Changes to repo.__class__, repo.dirstate.__class__
194 194 """
195 195 for c in self._repocallables:
196 196 with tracing.log('finalreposetup: %s', repr(c)):
197 197 c(ui, repo)
198 198
199 199 def uisetup(self, call):
200 200 """Decorated function will be executed during uisetup
201 201
202 202 example::
203 203
204 204 @eh.uisetup
205 205 def setupbabar(ui):
206 print 'this is uisetup!'
206 print('this is uisetup!')
207 207 """
208 208 self._uicallables.append(call)
209 209 return call
210 210
211 211 def uipopulate(self, call):
212 212 """Decorated function will be executed during uipopulate
213 213
214 214 example::
215 215
216 216 @eh.uipopulate
217 217 def setupfoo(ui):
218 print 'this is uipopulate!'
218 print('this is uipopulate!')
219 219 """
220 220 self._uipopulatecallables.append(call)
221 221 return call
222 222
223 223 def extsetup(self, call):
224 224 """Decorated function will be executed during extsetup
225 225
226 226 example::
227 227
228 228 @eh.extsetup
229 229 def setupcelestine(ui):
230 print 'this is extsetup!'
230 print('this is extsetup!')
231 231 """
232 232 self._extcallables.append(call)
233 233 return call
234 234
235 235 def reposetup(self, call):
236 236 """Decorated function will be executed during reposetup
237 237
238 238 example::
239 239
240 240 @eh.reposetup
241 241 def setupzephir(ui, repo):
242 print 'this is reposetup!'
242 print('this is reposetup!')
243 243 """
244 244 self._repocallables.append(call)
245 245 return call
246 246
247 247 def wrapcommand(self, command, extension=None, opts=None):
248 248 """Decorated function is a command wrapper
249 249
250 250 The name of the command must be given as the decorator argument.
251 251 The wrapping is installed during `uisetup`.
252 252
253 253 If the second option `extension` argument is provided, the wrapping
254 254 will be applied in the extension commandtable. This argument must be a
255 255 string that will be searched using `extension.find` if not found and
256 256 Abort error is raised. If the wrapping applies to an extension, it is
257 257 installed during `extsetup`.
258 258
259 259 example::
260 260
261 @eh.wrapcommand('summary')
261 @eh.wrapcommand(b'summary')
262 262 def wrapsummary(orig, ui, repo, *args, **kwargs):
263 ui.note('Barry!')
263 ui.note(b'Barry!')
264 264 return orig(ui, repo, *args, **kwargs)
265 265
266 266 The `opts` argument allows specifying a list of tuples for additional
267 267 arguments for the command. See ``mercurial.fancyopts.fancyopts()`` for
268 268 the format of the tuple.
269 269
270 270 """
271 271 if opts is None:
272 272 opts = []
273 273 else:
274 274 for opt in opts:
275 275 if not isinstance(opt, tuple):
276 276 raise error.ProgrammingError(b'opts must be list of tuples')
277 277 if len(opt) not in (4, 5):
278 278 msg = b'each opt tuple must contain 4 or 5 values'
279 279 raise error.ProgrammingError(msg)
280 280
281 281 def dec(wrapper):
282 282 if extension is None:
283 283 self._commandwrappers.append((command, wrapper, opts))
284 284 else:
285 285 self._extcommandwrappers.append(
286 286 (extension, command, wrapper, opts)
287 287 )
288 288 return wrapper
289 289
290 290 return dec
291 291
292 292 def wrapfunction(self, container, funcname):
293 293 """Decorated function is a function wrapper
294 294
295 295 This function takes two arguments, the container and the name of the
296 296 function to wrap. The wrapping is performed during `uisetup`.
297 297 (there is no extension support)
298 298
299 299 example::
300 300
301 @eh.function(discovery, 'checkheads')
301 @eh.function(discovery, b'checkheads')
302 302 def wrapfunction(orig, *args, **kwargs):
303 ui.note('His head smashed in and his heart cut out')
303 ui.note(b'His head smashed in and his heart cut out')
304 304 return orig(*args, **kwargs)
305 305 """
306 306
307 307 def dec(wrapper):
308 308 self._functionwrappers.append((container, funcname, wrapper))
309 309 return wrapper
310 310
311 311 return dec
General Comments 0
You need to be logged in to leave comments. Login now