##// END OF EJS Templates
peer: ensure command names are always ascii bytestrs...
Augie Fackler -
r34734:115efdd9 default
parent child Browse files
Show More
@@ -1,98 +1,100
1 # peer.py - repository base classes for mercurial
1 # peer.py - repository base classes for mercurial
2 #
2 #
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 from __future__ import absolute_import
9 from __future__ import absolute_import
10
10
11 from . import (
11 from . import (
12 error,
12 error,
13 pycompat,
13 util,
14 util,
14 )
15 )
15
16
16 # abstract batching support
17 # abstract batching support
17
18
18 class future(object):
19 class future(object):
19 '''placeholder for a value to be set later'''
20 '''placeholder for a value to be set later'''
20 def set(self, value):
21 def set(self, value):
21 if util.safehasattr(self, 'value'):
22 if util.safehasattr(self, 'value'):
22 raise error.RepoError("future is already set")
23 raise error.RepoError("future is already set")
23 self.value = value
24 self.value = value
24
25
25 class batcher(object):
26 class batcher(object):
26 '''base class for batches of commands submittable in a single request
27 '''base class for batches of commands submittable in a single request
27
28
28 All methods invoked on instances of this class are simply queued and
29 All methods invoked on instances of this class are simply queued and
29 return a a future for the result. Once you call submit(), all the queued
30 return a a future for the result. Once you call submit(), all the queued
30 calls are performed and the results set in their respective futures.
31 calls are performed and the results set in their respective futures.
31 '''
32 '''
32 def __init__(self):
33 def __init__(self):
33 self.calls = []
34 self.calls = []
34 def __getattr__(self, name):
35 def __getattr__(self, name):
35 def call(*args, **opts):
36 def call(*args, **opts):
36 resref = future()
37 resref = future()
37 # Please don't invent non-ascii method names, or you will
38 # Please don't invent non-ascii method names, or you will
38 # give core hg a very sad time.
39 # give core hg a very sad time.
39 self.calls.append((name.encode('ascii'), args, opts, resref,))
40 self.calls.append((name.encode('ascii'), args, opts, resref,))
40 return resref
41 return resref
41 return call
42 return call
42 def submit(self):
43 def submit(self):
43 raise NotImplementedError()
44 raise NotImplementedError()
44
45
45 class iterbatcher(batcher):
46 class iterbatcher(batcher):
46
47
47 def submit(self):
48 def submit(self):
48 raise NotImplementedError()
49 raise NotImplementedError()
49
50
50 def results(self):
51 def results(self):
51 raise NotImplementedError()
52 raise NotImplementedError()
52
53
53 class localiterbatcher(iterbatcher):
54 class localiterbatcher(iterbatcher):
54 def __init__(self, local):
55 def __init__(self, local):
55 super(iterbatcher, self).__init__()
56 super(iterbatcher, self).__init__()
56 self.local = local
57 self.local = local
57
58
58 def submit(self):
59 def submit(self):
59 # submit for a local iter batcher is a noop
60 # submit for a local iter batcher is a noop
60 pass
61 pass
61
62
62 def results(self):
63 def results(self):
63 for name, args, opts, resref in self.calls:
64 for name, args, opts, resref in self.calls:
64 resref.set(getattr(self.local, name)(*args, **opts))
65 resref.set(getattr(self.local, name)(*args, **opts))
65 yield resref.value
66 yield resref.value
66
67
67 def batchable(f):
68 def batchable(f):
68 '''annotation for batchable methods
69 '''annotation for batchable methods
69
70
70 Such methods must implement a coroutine as follows:
71 Such methods must implement a coroutine as follows:
71
72
72 @batchable
73 @batchable
73 def sample(self, one, two=None):
74 def sample(self, one, two=None):
74 # Build list of encoded arguments suitable for your wire protocol:
75 # Build list of encoded arguments suitable for your wire protocol:
75 encargs = [('one', encode(one),), ('two', encode(two),)]
76 encargs = [('one', encode(one),), ('two', encode(two),)]
76 # Create future for injection of encoded result:
77 # Create future for injection of encoded result:
77 encresref = future()
78 encresref = future()
78 # Return encoded arguments and future:
79 # Return encoded arguments and future:
79 yield encargs, encresref
80 yield encargs, encresref
80 # Assuming the future to be filled with the result from the batched
81 # Assuming the future to be filled with the result from the batched
81 # request now. Decode it:
82 # request now. Decode it:
82 yield decode(encresref.value)
83 yield decode(encresref.value)
83
84
84 The decorator returns a function which wraps this coroutine as a plain
85 The decorator returns a function which wraps this coroutine as a plain
85 method, but adds the original method as an attribute called "batchable",
86 method, but adds the original method as an attribute called "batchable",
86 which is used by remotebatch to split the call into separate encoding and
87 which is used by remotebatch to split the call into separate encoding and
87 decoding phases.
88 decoding phases.
88 '''
89 '''
89 def plain(*args, **opts):
90 def plain(*args, **opts):
90 batchable = f(*args, **opts)
91 batchable = f(*args, **opts)
91 encargsorres, encresref = next(batchable)
92 encargsorres, encresref = next(batchable)
92 if not encresref:
93 if not encresref:
93 return encargsorres # a local result in this case
94 return encargsorres # a local result in this case
94 self = args[0]
95 self = args[0]
95 encresref.set(self._submitone(f.__name__, encargsorres))
96 cmd = pycompat.bytesurl(f.__name__) # ensure cmd is ascii bytestr
97 encresref.set(self._submitone(cmd, encargsorres))
96 return next(batchable)
98 return next(batchable)
97 setattr(plain, 'batchable', f)
99 setattr(plain, 'batchable', f)
98 return plain
100 return plain
General Comments 0
You need to be logged in to leave comments. Login now