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