##// END OF EJS Templates
registrar: raise a programming error on duplicated registering...
Pierre-Yves David -
r30608:b52e8a4f default
parent child Browse files
Show More
@@ -1,249 +1,254 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 error,
11 12 pycompat,
12 13 util,
13 14 )
14 15
15 16 class _funcregistrarbase(object):
16 17 """Base of decorator to register a function for specific purpose
17 18
18 19 This decorator stores decorated functions into own dict 'table'.
19 20
20 21 The least derived class can be defined by overriding 'formatdoc',
21 22 for example::
22 23
23 24 class keyword(_funcregistrarbase):
24 25 _docformat = ":%s: %s"
25 26
26 27 This should be used as below:
27 28
28 29 keyword = registrar.keyword()
29 30
30 31 @keyword('bar')
31 32 def barfunc(*args, **kwargs):
32 33 '''Explanation of bar keyword ....
33 34 '''
34 35 pass
35 36
36 37 In this case:
37 38
38 39 - 'barfunc' is stored as 'bar' in '_table' of an instance 'keyword' above
39 40 - 'barfunc.__doc__' becomes ":bar: Explanation of bar keyword"
40 41 """
41 42 def __init__(self, table=None):
42 43 if table is None:
43 44 self._table = {}
44 45 else:
45 46 self._table = table
46 47
47 48 def __call__(self, decl, *args, **kwargs):
48 49 return lambda func: self._doregister(func, decl, *args, **kwargs)
49 50
50 51 def _doregister(self, func, decl, *args, **kwargs):
51 52 name = self._getname(decl)
52 53
54 if name in self._table:
55 msg = 'duplicate registration for name: "%s"' % name
56 raise error.ProgrammingError(msg)
57
53 58 if func.__doc__ and not util.safehasattr(func, '_origdoc'):
54 59 doc = func.__doc__.strip()
55 60 func._origdoc = doc
56 61 func.__doc__ = self._formatdoc(decl, doc)
57 62
58 63 self._table[name] = func
59 64 self._extrasetup(name, func, *args, **kwargs)
60 65
61 66 return func
62 67
63 68 def _parsefuncdecl(self, decl):
64 69 """Parse function declaration and return the name of function in it
65 70 """
66 71 i = decl.find('(')
67 72 if i >= 0:
68 73 return decl[:i]
69 74 else:
70 75 return decl
71 76
72 77 def _getname(self, decl):
73 78 """Return the name of the registered function from decl
74 79
75 80 Derived class should override this, if it allows more
76 81 descriptive 'decl' string than just a name.
77 82 """
78 83 return decl
79 84
80 85 _docformat = None
81 86
82 87 def _formatdoc(self, decl, doc):
83 88 """Return formatted document of the registered function for help
84 89
85 90 'doc' is '__doc__.strip()' of the registered function.
86 91 """
87 92 return self._docformat % (decl, doc)
88 93
89 94 def _extrasetup(self, name, func):
90 95 """Execute exra setup for registered function, if needed
91 96 """
92 97 pass
93 98
94 99 class revsetpredicate(_funcregistrarbase):
95 100 """Decorator to register revset predicate
96 101
97 102 Usage::
98 103
99 104 revsetpredicate = registrar.revsetpredicate()
100 105
101 106 @revsetpredicate('mypredicate(arg1, arg2[, arg3])')
102 107 def mypredicatefunc(repo, subset, x):
103 108 '''Explanation of this revset predicate ....
104 109 '''
105 110 pass
106 111
107 112 The first string argument is used also in online help.
108 113
109 114 Optional argument 'safe' indicates whether a predicate is safe for
110 115 DoS attack (False by default).
111 116
112 117 Optional argument 'takeorder' indicates whether a predicate function
113 118 takes ordering policy as the last argument.
114 119
115 120 'revsetpredicate' instance in example above can be used to
116 121 decorate multiple functions.
117 122
118 123 Decorated functions are registered automatically at loading
119 124 extension, if an instance named as 'revsetpredicate' is used for
120 125 decorating in extension.
121 126
122 127 Otherwise, explicit 'revset.loadpredicate()' is needed.
123 128 """
124 129 _getname = _funcregistrarbase._parsefuncdecl
125 130 _docformat = pycompat.sysstr("``%s``\n %s")
126 131
127 132 def _extrasetup(self, name, func, safe=False, takeorder=False):
128 133 func._safe = safe
129 134 func._takeorder = takeorder
130 135
131 136 class filesetpredicate(_funcregistrarbase):
132 137 """Decorator to register fileset predicate
133 138
134 139 Usage::
135 140
136 141 filesetpredicate = registrar.filesetpredicate()
137 142
138 143 @filesetpredicate('mypredicate()')
139 144 def mypredicatefunc(mctx, x):
140 145 '''Explanation of this fileset predicate ....
141 146 '''
142 147 pass
143 148
144 149 The first string argument is used also in online help.
145 150
146 151 Optional argument 'callstatus' indicates whether a predicate
147 152 implies 'matchctx.status()' at runtime or not (False, by
148 153 default).
149 154
150 155 Optional argument 'callexisting' indicates whether a predicate
151 156 implies 'matchctx.existing()' at runtime or not (False, by
152 157 default).
153 158
154 159 'filesetpredicate' instance in example above can be used to
155 160 decorate multiple functions.
156 161
157 162 Decorated functions are registered automatically at loading
158 163 extension, if an instance named as 'filesetpredicate' is used for
159 164 decorating in extension.
160 165
161 166 Otherwise, explicit 'fileset.loadpredicate()' is needed.
162 167 """
163 168 _getname = _funcregistrarbase._parsefuncdecl
164 169 _docformat = pycompat.sysstr("``%s``\n %s")
165 170
166 171 def _extrasetup(self, name, func, callstatus=False, callexisting=False):
167 172 func._callstatus = callstatus
168 173 func._callexisting = callexisting
169 174
170 175 class _templateregistrarbase(_funcregistrarbase):
171 176 """Base of decorator to register functions as template specific one
172 177 """
173 178 _docformat = pycompat.sysstr(":%s: %s")
174 179
175 180 class templatekeyword(_templateregistrarbase):
176 181 """Decorator to register template keyword
177 182
178 183 Usage::
179 184
180 185 templatekeyword = registrar.templatekeyword()
181 186
182 187 @templatekeyword('mykeyword')
183 188 def mykeywordfunc(repo, ctx, templ, cache, revcache, **args):
184 189 '''Explanation of this template keyword ....
185 190 '''
186 191 pass
187 192
188 193 The first string argument is used also in online help.
189 194
190 195 'templatekeyword' instance in example above can be used to
191 196 decorate multiple functions.
192 197
193 198 Decorated functions are registered automatically at loading
194 199 extension, if an instance named as 'templatekeyword' is used for
195 200 decorating in extension.
196 201
197 202 Otherwise, explicit 'templatekw.loadkeyword()' is needed.
198 203 """
199 204
200 205 class templatefilter(_templateregistrarbase):
201 206 """Decorator to register template filer
202 207
203 208 Usage::
204 209
205 210 templatefilter = registrar.templatefilter()
206 211
207 212 @templatefilter('myfilter')
208 213 def myfilterfunc(text):
209 214 '''Explanation of this template filter ....
210 215 '''
211 216 pass
212 217
213 218 The first string argument is used also in online help.
214 219
215 220 'templatefilter' instance in example above can be used to
216 221 decorate multiple functions.
217 222
218 223 Decorated functions are registered automatically at loading
219 224 extension, if an instance named as 'templatefilter' is used for
220 225 decorating in extension.
221 226
222 227 Otherwise, explicit 'templatefilters.loadkeyword()' is needed.
223 228 """
224 229
225 230 class templatefunc(_templateregistrarbase):
226 231 """Decorator to register template function
227 232
228 233 Usage::
229 234
230 235 templatefunc = registrar.templatefunc()
231 236
232 237 @templatefunc('myfunc(arg1, arg2[, arg3])')
233 238 def myfuncfunc(context, mapping, args):
234 239 '''Explanation of this template function ....
235 240 '''
236 241 pass
237 242
238 243 The first string argument is used also in online help.
239 244
240 245 'templatefunc' instance in example above can be used to
241 246 decorate multiple functions.
242 247
243 248 Decorated functions are registered automatically at loading
244 249 extension, if an instance named as 'templatefunc' is used for
245 250 decorating in extension.
246 251
247 252 Otherwise, explicit 'templater.loadfunction()' is needed.
248 253 """
249 254 _getname = _funcregistrarbase._parsefuncdecl
General Comments 0
You need to be logged in to leave comments. Login now