wireproto: move command registration types to wireprototypes
These are shared across wire protocol implementations. wireprototypes
is our module for common code.
Differential Revision: https://phab.mercurial-scm.org/D3396
--- a/mercurial/wireproto.py Mon Apr 16 21:49:59 2018 -0700
+++ b/mercurial/wireproto.py Mon Apr 16 21:52:33 2018 -0700
@@ -173,89 +173,11 @@
return compengines
-class commandentry(object):
- """Represents a declared wire protocol command."""
- def __init__(self, func, args='', transports=None,
- permission='push'):
- self.func = func
- self.args = args
- self.transports = transports or set()
- self.permission = permission
-
- def _merge(self, func, args):
- """Merge this instance with an incoming 2-tuple.
-
- This is called when a caller using the old 2-tuple API attempts
- to replace an instance. The incoming values are merged with
- data not captured by the 2-tuple and a new instance containing
- the union of the two objects is returned.
- """
- return commandentry(func, args=args, transports=set(self.transports),
- permission=self.permission)
-
- # Old code treats instances as 2-tuples. So expose that interface.
- def __iter__(self):
- yield self.func
- yield self.args
-
- def __getitem__(self, i):
- if i == 0:
- return self.func
- elif i == 1:
- return self.args
- else:
- raise IndexError('can only access elements 0 and 1')
-
-class commanddict(dict):
- """Container for registered wire protocol commands.
-
- It behaves like a dict. But __setitem__ is overwritten to allow silent
- coercion of values from 2-tuples for API compatibility.
- """
- def __setitem__(self, k, v):
- if isinstance(v, commandentry):
- pass
- # Cast 2-tuples to commandentry instances.
- elif isinstance(v, tuple):
- if len(v) != 2:
- raise ValueError('command tuples must have exactly 2 elements')
-
- # It is common for extensions to wrap wire protocol commands via
- # e.g. ``wireproto.commands[x] = (newfn, args)``. Because callers
- # doing this aren't aware of the new API that uses objects to store
- # command entries, we automatically merge old state with new.
- if k in self:
- v = self[k]._merge(v[0], v[1])
- else:
- # Use default values from @wireprotocommand.
- v = commandentry(v[0], args=v[1],
- transports=set(wireprototypes.TRANSPORTS),
- permission='push')
- else:
- raise ValueError('command entries must be commandentry instances '
- 'or 2-tuples')
-
- return super(commanddict, self).__setitem__(k, v)
-
- def commandavailable(self, command, proto):
- """Determine if a command is available for the requested protocol."""
- assert proto.name in wireprototypes.TRANSPORTS
-
- entry = self.get(command)
-
- if not entry:
- return False
-
- if proto.name not in entry.transports:
- return False
-
- return True
-
# For version 1 transports.
-commands = commanddict()
+commands = wireprototypes.commanddict()
# For version 2 transports.
-commandsv2 = commanddict()
+commandsv2 = wireprototypes.commanddict()
def wireprotocommand(name, args=None, permission='push'):
"""Decorator to declare a wire protocol command.
@@ -297,9 +219,8 @@
if name in commands:
raise error.ProgrammingError('%s command already registered '
'for version 1' % name)
- commands[name] = commandentry(func, args=args,
- transports=transports,
- permission=permission)
+ commands[name] = wireprototypes.commandentry(
+ func, args=args, transports=transports, permission=permission)
return func
return register
--- a/mercurial/wireprototypes.py Mon Apr 16 21:49:59 2018 -0700
+++ b/mercurial/wireprototypes.py Mon Apr 16 21:52:33 2018 -0700
@@ -241,3 +241,81 @@
doesn't have that permission, the exception should raise or abort
in a protocol specific manner.
"""
+
+class commandentry(object):
+ """Represents a declared wire protocol command."""
+ def __init__(self, func, args='', transports=None,
+ permission='push'):
+ self.func = func
+ self.args = args
+ self.transports = transports or set()
+ self.permission = permission
+
+ def _merge(self, func, args):
+ """Merge this instance with an incoming 2-tuple.
+
+ This is called when a caller using the old 2-tuple API attempts
+ to replace an instance. The incoming values are merged with
+ data not captured by the 2-tuple and a new instance containing
+ the union of the two objects is returned.
+ """
+ return commandentry(func, args=args, transports=set(self.transports),
+ permission=self.permission)
+
+ # Old code treats instances as 2-tuples. So expose that interface.
+ def __iter__(self):
+ yield self.func
+ yield self.args
+
+ def __getitem__(self, i):
+ if i == 0:
+ return self.func
+ elif i == 1:
+ return self.args
+ else:
+ raise IndexError('can only access elements 0 and 1')
+
+class commanddict(dict):
+ """Container for registered wire protocol commands.
+
+ It behaves like a dict. But __setitem__ is overwritten to allow silent
+ coercion of values from 2-tuples for API compatibility.
+ """
+ def __setitem__(self, k, v):
+ if isinstance(v, commandentry):
+ pass
+ # Cast 2-tuples to commandentry instances.
+ elif isinstance(v, tuple):
+ if len(v) != 2:
+ raise ValueError('command tuples must have exactly 2 elements')
+
+ # It is common for extensions to wrap wire protocol commands via
+ # e.g. ``wireproto.commands[x] = (newfn, args)``. Because callers
+ # doing this aren't aware of the new API that uses objects to store
+ # command entries, we automatically merge old state with new.
+ if k in self:
+ v = self[k]._merge(v[0], v[1])
+ else:
+ # Use default values from @wireprotocommand.
+ v = commandentry(v[0], args=v[1],
+ transports=set(TRANSPORTS),
+ permission='push')
+ else:
+ raise ValueError('command entries must be commandentry instances '
+ 'or 2-tuples')
+
+ return super(commanddict, self).__setitem__(k, v)
+
+ def commandavailable(self, command, proto):
+ """Determine if a command is available for the requested protocol."""
+ assert proto.name in TRANSPORTS
+
+ entry = self.get(command)
+
+ if not entry:
+ return False
+
+ if proto.name not in entry.transports:
+ return False
+
+ return True
--- a/mercurial/wireprotov2server.py Mon Apr 16 21:49:59 2018 -0700
+++ b/mercurial/wireprotov2server.py Mon Apr 16 21:52:33 2018 -0700
@@ -438,7 +438,7 @@
raise error.ProgrammingError('%s command already registered '
'for version 2' % name)
- wireproto.commandsv2[name] = wireproto.commandentry(
+ wireproto.commandsv2[name] = wireprototypes.commandentry(
func, args=args, transports=transports, permission=permission)
return func