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