##// END OF EJS Templates
wireproto: move command registration types to wireprototypes...
Gregory Szorc -
r37799:352932a1 default
parent child Browse files
Show More
@@ -173,89 +173,11 b' def supportedcompengines(ui, role):'
173 173
174 174 return compengines
175 175
176 class commandentry(object):
177 """Represents a declared wire protocol command."""
178 def __init__(self, func, args='', transports=None,
179 permission='push'):
180 self.func = func
181 self.args = args
182 self.transports = transports or set()
183 self.permission = permission
184
185 def _merge(self, func, args):
186 """Merge this instance with an incoming 2-tuple.
187
188 This is called when a caller using the old 2-tuple API attempts
189 to replace an instance. The incoming values are merged with
190 data not captured by the 2-tuple and a new instance containing
191 the union of the two objects is returned.
192 """
193 return commandentry(func, args=args, transports=set(self.transports),
194 permission=self.permission)
195
196 # Old code treats instances as 2-tuples. So expose that interface.
197 def __iter__(self):
198 yield self.func
199 yield self.args
200
201 def __getitem__(self, i):
202 if i == 0:
203 return self.func
204 elif i == 1:
205 return self.args
206 else:
207 raise IndexError('can only access elements 0 and 1')
208
209 class commanddict(dict):
210 """Container for registered wire protocol commands.
211
212 It behaves like a dict. But __setitem__ is overwritten to allow silent
213 coercion of values from 2-tuples for API compatibility.
214 """
215 def __setitem__(self, k, v):
216 if isinstance(v, commandentry):
217 pass
218 # Cast 2-tuples to commandentry instances.
219 elif isinstance(v, tuple):
220 if len(v) != 2:
221 raise ValueError('command tuples must have exactly 2 elements')
222
223 # It is common for extensions to wrap wire protocol commands via
224 # e.g. ``wireproto.commands[x] = (newfn, args)``. Because callers
225 # doing this aren't aware of the new API that uses objects to store
226 # command entries, we automatically merge old state with new.
227 if k in self:
228 v = self[k]._merge(v[0], v[1])
229 else:
230 # Use default values from @wireprotocommand.
231 v = commandentry(v[0], args=v[1],
232 transports=set(wireprototypes.TRANSPORTS),
233 permission='push')
234 else:
235 raise ValueError('command entries must be commandentry instances '
236 'or 2-tuples')
237
238 return super(commanddict, self).__setitem__(k, v)
239
240 def commandavailable(self, command, proto):
241 """Determine if a command is available for the requested protocol."""
242 assert proto.name in wireprototypes.TRANSPORTS
243
244 entry = self.get(command)
245
246 if not entry:
247 return False
248
249 if proto.name not in entry.transports:
250 return False
251
252 return True
253
254 176 # For version 1 transports.
255 commands = commanddict()
177 commands = wireprototypes.commanddict()
256 178
257 179 # For version 2 transports.
258 commandsv2 = commanddict()
180 commandsv2 = wireprototypes.commanddict()
259 181
260 182 def wireprotocommand(name, args=None, permission='push'):
261 183 """Decorator to declare a wire protocol command.
@@ -297,9 +219,8 b' def wireprotocommand(name, args=None, pe'
297 219 if name in commands:
298 220 raise error.ProgrammingError('%s command already registered '
299 221 'for version 1' % name)
300 commands[name] = commandentry(func, args=args,
301 transports=transports,
302 permission=permission)
222 commands[name] = wireprototypes.commandentry(
223 func, args=args, transports=transports, permission=permission)
303 224
304 225 return func
305 226 return register
@@ -241,3 +241,81 b' class baseprotocolhandler(zi.Interface):'
241 241 doesn't have that permission, the exception should raise or abort
242 242 in a protocol specific manner.
243 243 """
244
245 class commandentry(object):
246 """Represents a declared wire protocol command."""
247 def __init__(self, func, args='', transports=None,
248 permission='push'):
249 self.func = func
250 self.args = args
251 self.transports = transports or set()
252 self.permission = permission
253
254 def _merge(self, func, args):
255 """Merge this instance with an incoming 2-tuple.
256
257 This is called when a caller using the old 2-tuple API attempts
258 to replace an instance. The incoming values are merged with
259 data not captured by the 2-tuple and a new instance containing
260 the union of the two objects is returned.
261 """
262 return commandentry(func, args=args, transports=set(self.transports),
263 permission=self.permission)
264
265 # Old code treats instances as 2-tuples. So expose that interface.
266 def __iter__(self):
267 yield self.func
268 yield self.args
269
270 def __getitem__(self, i):
271 if i == 0:
272 return self.func
273 elif i == 1:
274 return self.args
275 else:
276 raise IndexError('can only access elements 0 and 1')
277
278 class commanddict(dict):
279 """Container for registered wire protocol commands.
280
281 It behaves like a dict. But __setitem__ is overwritten to allow silent
282 coercion of values from 2-tuples for API compatibility.
283 """
284 def __setitem__(self, k, v):
285 if isinstance(v, commandentry):
286 pass
287 # Cast 2-tuples to commandentry instances.
288 elif isinstance(v, tuple):
289 if len(v) != 2:
290 raise ValueError('command tuples must have exactly 2 elements')
291
292 # It is common for extensions to wrap wire protocol commands via
293 # e.g. ``wireproto.commands[x] = (newfn, args)``. Because callers
294 # doing this aren't aware of the new API that uses objects to store
295 # command entries, we automatically merge old state with new.
296 if k in self:
297 v = self[k]._merge(v[0], v[1])
298 else:
299 # Use default values from @wireprotocommand.
300 v = commandentry(v[0], args=v[1],
301 transports=set(TRANSPORTS),
302 permission='push')
303 else:
304 raise ValueError('command entries must be commandentry instances '
305 'or 2-tuples')
306
307 return super(commanddict, self).__setitem__(k, v)
308
309 def commandavailable(self, command, proto):
310 """Determine if a command is available for the requested protocol."""
311 assert proto.name in TRANSPORTS
312
313 entry = self.get(command)
314
315 if not entry:
316 return False
317
318 if proto.name not in entry.transports:
319 return False
320
321 return True
@@ -438,7 +438,7 b' def wireprotocommand(name, args=None, pe'
438 438 raise error.ProgrammingError('%s command already registered '
439 439 'for version 2' % name)
440 440
441 wireproto.commandsv2[name] = wireproto.commandentry(
441 wireproto.commandsv2[name] = wireprototypes.commandentry(
442 442 func, args=args, transports=transports, permission=permission)
443 443
444 444 return func
General Comments 0
You need to be logged in to leave comments. Login now