##// END OF EJS Templates
registrar: fixing typo in comment...
Saurabh Singh -
r34437:c1fe66e8 default
parent child Browse files
Show More
@@ -1,381 +1,381 b''
1 1 # registrar.py - utilities to register function for specific purpose
2 2 #
3 3 # Copyright FUJIWARA Katsunori <foozy@lares.dti.ne.jp> and others
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 from . import (
11 11 configitems,
12 12 error,
13 13 pycompat,
14 14 util,
15 15 )
16 16
17 17 # unlike the other registered items, config options are neither functions or
18 18 # classes. Registering the option is just small function call.
19 19 #
20 20 # We still add the official API to the registrar module for consistency with
21 21 # the other items extensions want might to register.
22 22 configitem = configitems.getitemregister
23 23
24 24 class _funcregistrarbase(object):
25 25 """Base of decorator to register a function for specific purpose
26 26
27 27 This decorator stores decorated functions into own dict 'table'.
28 28
29 29 The least derived class can be defined by overriding 'formatdoc',
30 30 for example::
31 31
32 32 class keyword(_funcregistrarbase):
33 33 _docformat = ":%s: %s"
34 34
35 35 This should be used as below:
36 36
37 37 keyword = registrar.keyword()
38 38
39 39 @keyword('bar')
40 40 def barfunc(*args, **kwargs):
41 41 '''Explanation of bar keyword ....
42 42 '''
43 43 pass
44 44
45 45 In this case:
46 46
47 47 - 'barfunc' is stored as 'bar' in '_table' of an instance 'keyword' above
48 48 - 'barfunc.__doc__' becomes ":bar: Explanation of bar keyword"
49 49 """
50 50 def __init__(self, table=None):
51 51 if table is None:
52 52 self._table = {}
53 53 else:
54 54 self._table = table
55 55
56 56 def __call__(self, decl, *args, **kwargs):
57 57 return lambda func: self._doregister(func, decl, *args, **kwargs)
58 58
59 59 def _doregister(self, func, decl, *args, **kwargs):
60 60 name = self._getname(decl)
61 61
62 62 if name in self._table:
63 63 msg = 'duplicate registration for name: "%s"' % name
64 64 raise error.ProgrammingError(msg)
65 65
66 66 if func.__doc__ and not util.safehasattr(func, '_origdoc'):
67 67 doc = pycompat.sysbytes(func.__doc__).strip()
68 68 func._origdoc = doc
69 69 func.__doc__ = pycompat.sysstr(self._formatdoc(decl, doc))
70 70
71 71 self._table[name] = func
72 72 self._extrasetup(name, func, *args, **kwargs)
73 73
74 74 return func
75 75
76 76 def _parsefuncdecl(self, decl):
77 77 """Parse function declaration and return the name of function in it
78 78 """
79 79 i = decl.find('(')
80 80 if i >= 0:
81 81 return decl[:i]
82 82 else:
83 83 return decl
84 84
85 85 def _getname(self, decl):
86 86 """Return the name of the registered function from decl
87 87
88 88 Derived class should override this, if it allows more
89 89 descriptive 'decl' string than just a name.
90 90 """
91 91 return decl
92 92
93 93 _docformat = None
94 94
95 95 def _formatdoc(self, decl, doc):
96 96 """Return formatted document of the registered function for help
97 97
98 98 'doc' is '__doc__.strip()' of the registered function.
99 99 """
100 100 return self._docformat % (decl, doc)
101 101
102 102 def _extrasetup(self, name, func):
103 103 """Execute exra setup for registered function, if needed
104 104 """
105 105
106 106 class command(_funcregistrarbase):
107 107 """Decorator to register a command function to table
108 108
109 109 This class receives a command table as its argument. The table should
110 110 be a dict.
111 111
112 112 The created object can be used as a decorator for adding commands to
113 113 that command table. This accepts multiple arguments to define a command.
114 114
115 115 The first argument is the command name.
116 116
117 117 The options argument is an iterable of tuples defining command arguments.
118 118 See ``mercurial.fancyopts.fancyopts()`` for the format of each tuple.
119 119
120 120 The synopsis argument defines a short, one line summary of how to use the
121 121 command. This shows up in the help output.
122 122
123 123 The norepo argument defines whether the command does not require a
124 124 local repository. Most commands operate against a repository, thus the
125 125 default is False.
126 126
127 127 The optionalrepo argument defines whether the command optionally requires
128 128 a local repository.
129 129
130 130 The inferrepo argument defines whether to try to find a repository from the
131 131 command line arguments. If True, arguments will be examined for potential
132 132 repository locations. See ``findrepo()``. If a repository is found, it
133 133 will be used.
134 134 """
135 135
136 136 def _doregister(self, func, name, options=(), synopsis=None,
137 137 norepo=False, optionalrepo=False, inferrepo=False):
138 138 func.norepo = norepo
139 139 func.optionalrepo = optionalrepo
140 140 func.inferrepo = inferrepo
141 141 if synopsis:
142 142 self._table[name] = func, list(options), synopsis
143 143 else:
144 144 self._table[name] = func, list(options)
145 145 return func
146 146
147 147 class revsetpredicate(_funcregistrarbase):
148 148 """Decorator to register revset predicate
149 149
150 150 Usage::
151 151
152 152 revsetpredicate = registrar.revsetpredicate()
153 153
154 154 @revsetpredicate('mypredicate(arg1, arg2[, arg3])')
155 155 def mypredicatefunc(repo, subset, x):
156 156 '''Explanation of this revset predicate ....
157 157 '''
158 158 pass
159 159
160 160 The first string argument is used also in online help.
161 161
162 162 Optional argument 'safe' indicates whether a predicate is safe for
163 163 DoS attack (False by default).
164 164
165 165 Optional argument 'takeorder' indicates whether a predicate function
166 166 takes ordering policy as the last argument.
167 167
168 168 Optional argument 'weight' indicates the estimated run-time cost, useful
169 169 for static optimization, default is 1. Higher weight means more expensive.
170 170 Usually, revsets that are fast and return only one revision has a weight of
171 171 0.5 (ex. a symbol); revsets with O(changelog) complexity and read only the
172 172 changelog have weight 10 (ex. author); revsets reading manifest deltas have
173 173 weight 30 (ex. adds); revset reading manifest contents have weight 100
174 174 (ex. contains). Note: those values are flexible. If the revset has a
175 175 same big-O time complexity as 'contains', but with a smaller constant, it
176 176 might have a weight of 90.
177 177
178 178 'revsetpredicate' instance in example above can be used to
179 179 decorate multiple functions.
180 180
181 181 Decorated functions are registered automatically at loading
182 182 extension, if an instance named as 'revsetpredicate' is used for
183 183 decorating in extension.
184 184
185 185 Otherwise, explicit 'revset.loadpredicate()' is needed.
186 186 """
187 187 _getname = _funcregistrarbase._parsefuncdecl
188 188 _docformat = "``%s``\n %s"
189 189
190 190 def _extrasetup(self, name, func, safe=False, takeorder=False, weight=1):
191 191 func._safe = safe
192 192 func._takeorder = takeorder
193 193 func._weight = weight
194 194
195 195 class filesetpredicate(_funcregistrarbase):
196 196 """Decorator to register fileset predicate
197 197
198 198 Usage::
199 199
200 200 filesetpredicate = registrar.filesetpredicate()
201 201
202 202 @filesetpredicate('mypredicate()')
203 203 def mypredicatefunc(mctx, x):
204 204 '''Explanation of this fileset predicate ....
205 205 '''
206 206 pass
207 207
208 208 The first string argument is used also in online help.
209 209
210 210 Optional argument 'callstatus' indicates whether a predicate
211 211 implies 'matchctx.status()' at runtime or not (False, by
212 212 default).
213 213
214 214 Optional argument 'callexisting' indicates whether a predicate
215 215 implies 'matchctx.existing()' at runtime or not (False, by
216 216 default).
217 217
218 218 'filesetpredicate' instance in example above can be used to
219 219 decorate multiple functions.
220 220
221 221 Decorated functions are registered automatically at loading
222 222 extension, if an instance named as 'filesetpredicate' is used for
223 223 decorating in extension.
224 224
225 225 Otherwise, explicit 'fileset.loadpredicate()' is needed.
226 226 """
227 227 _getname = _funcregistrarbase._parsefuncdecl
228 228 _docformat = "``%s``\n %s"
229 229
230 230 def _extrasetup(self, name, func, callstatus=False, callexisting=False):
231 231 func._callstatus = callstatus
232 232 func._callexisting = callexisting
233 233
234 234 class _templateregistrarbase(_funcregistrarbase):
235 235 """Base of decorator to register functions as template specific one
236 236 """
237 237 _docformat = ":%s: %s"
238 238
239 239 class templatekeyword(_templateregistrarbase):
240 240 """Decorator to register template keyword
241 241
242 242 Usage::
243 243
244 244 templatekeyword = registrar.templatekeyword()
245 245
246 246 @templatekeyword('mykeyword')
247 247 def mykeywordfunc(repo, ctx, templ, cache, revcache, **args):
248 248 '''Explanation of this template keyword ....
249 249 '''
250 250 pass
251 251
252 252 The first string argument is used also in online help.
253 253
254 254 'templatekeyword' instance in example above can be used to
255 255 decorate multiple functions.
256 256
257 257 Decorated functions are registered automatically at loading
258 258 extension, if an instance named as 'templatekeyword' is used for
259 259 decorating in extension.
260 260
261 261 Otherwise, explicit 'templatekw.loadkeyword()' is needed.
262 262 """
263 263
264 264 class templatefilter(_templateregistrarbase):
265 265 """Decorator to register template filer
266 266
267 267 Usage::
268 268
269 269 templatefilter = registrar.templatefilter()
270 270
271 271 @templatefilter('myfilter')
272 272 def myfilterfunc(text):
273 273 '''Explanation of this template filter ....
274 274 '''
275 275 pass
276 276
277 277 The first string argument is used also in online help.
278 278
279 279 'templatefilter' instance in example above can be used to
280 280 decorate multiple functions.
281 281
282 282 Decorated functions are registered automatically at loading
283 283 extension, if an instance named as 'templatefilter' is used for
284 284 decorating in extension.
285 285
286 286 Otherwise, explicit 'templatefilters.loadkeyword()' is needed.
287 287 """
288 288
289 289 class templatefunc(_templateregistrarbase):
290 290 """Decorator to register template function
291 291
292 292 Usage::
293 293
294 294 templatefunc = registrar.templatefunc()
295 295
296 296 @templatefunc('myfunc(arg1, arg2[, arg3])', argspec='arg1 arg2 arg3')
297 297 def myfuncfunc(context, mapping, args):
298 298 '''Explanation of this template function ....
299 299 '''
300 300 pass
301 301
302 302 The first string argument is used also in online help.
303 303
304 304 If optional 'argspec' is defined, the function will receive 'args' as
305 305 a dict of named arguments. Otherwise 'args' is a list of positional
306 306 arguments.
307 307
308 308 'templatefunc' instance in example above can be used to
309 309 decorate multiple functions.
310 310
311 311 Decorated functions are registered automatically at loading
312 312 extension, if an instance named as 'templatefunc' is used for
313 313 decorating in extension.
314 314
315 315 Otherwise, explicit 'templater.loadfunction()' is needed.
316 316 """
317 317 _getname = _funcregistrarbase._parsefuncdecl
318 318
319 319 def _extrasetup(self, name, func, argspec=None):
320 320 func._argspec = argspec
321 321
322 322 class internalmerge(_funcregistrarbase):
323 323 """Decorator to register in-process merge tool
324 324
325 325 Usage::
326 326
327 327 internalmerge = registrar.internalmerge()
328 328
329 329 @internalmerge('mymerge', internalmerge.mergeonly,
330 330 onfailure=None, precheck=None):
331 331 def mymergefunc(repo, mynode, orig, fcd, fco, fca,
332 332 toolconf, files, labels=None):
333 333 '''Explanation of this internal merge tool ....
334 334 '''
335 335 return 1, False # means "conflicted", "no deletion needed"
336 336
337 337 The first string argument is used to compose actual merge tool name,
338 338 ":name" and "internal:name" (the latter is historical one).
339 339
340 340 The second argument is one of merge types below:
341 341
342 342 ========== ======== ======== =========
343 343 merge type precheck premerge fullmerge
344 344 ========== ======== ======== =========
345 345 nomerge x x x
346 346 mergeonly o x o
347 347 fullmerge o o o
348 348 ========== ======== ======== =========
349 349
350 Optional argument 'onfalure' is the format of warning message
350 Optional argument 'onfailure' is the format of warning message
351 351 to be used at failure of merging (target filename is specified
352 352 at formatting). Or, None or so, if warning message should be
353 353 suppressed.
354 354
355 355 Optional argument 'precheck' is the function to be used
356 356 before actual invocation of internal merge tool itself.
357 357 It takes as same arguments as internal merge tool does, other than
358 358 'files' and 'labels'. If it returns false value, merging is aborted
359 359 immediately (and file is marked as "unresolved").
360 360
361 361 'internalmerge' instance in example above can be used to
362 362 decorate multiple functions.
363 363
364 364 Decorated functions are registered automatically at loading
365 365 extension, if an instance named as 'internalmerge' is used for
366 366 decorating in extension.
367 367
368 368 Otherwise, explicit 'filemerge.loadinternalmerge()' is needed.
369 369 """
370 370 _docformat = "``:%s``\n %s"
371 371
372 372 # merge type definitions:
373 373 nomerge = None
374 374 mergeonly = 'mergeonly' # just the full merge, no premerge
375 375 fullmerge = 'fullmerge' # both premerge and merge
376 376
377 377 def _extrasetup(self, name, func, mergetype,
378 378 onfailure=None, precheck=None):
379 379 func.mergetype = mergetype
380 380 func.onfailure = onfailure
381 381 func.precheck = precheck
General Comments 0
You need to be logged in to leave comments. Login now