##// END OF EJS Templates
test-batching: stop direct symbol import of mercurial modules...
Yuya Nishihara -
r28800:544908ae default
parent child Browse files
Show More
@@ -1,183 +1,180 b''
1 1 # test-batching.py - tests for transparent command batching
2 2 #
3 3 # Copyright 2011 Peter Arrenbrecht <peter@arrenbrecht.ch>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import, print_function
9 from mercurial.peer import (
10 localbatch,
11 batchable,
12 future,
13 )
14 from mercurial.wireproto import (
15 remotebatch,
9
10 from mercurial import (
11 peer,
12 wireproto,
16 13 )
17 14
18 15 # equivalent of repo.repository
19 16 class thing(object):
20 17 def hello(self):
21 18 return "Ready."
22 19
23 20 # equivalent of localrepo.localrepository
24 21 class localthing(thing):
25 22 def foo(self, one, two=None):
26 23 if one:
27 24 return "%s and %s" % (one, two,)
28 25 return "Nope"
29 26 def bar(self, b, a):
30 27 return "%s und %s" % (b, a,)
31 28 def greet(self, name=None):
32 29 return "Hello, %s" % name
33 30 def batch(self):
34 31 '''Support for local batching.'''
35 return localbatch(self)
32 return peer.localbatch(self)
36 33
37 34 # usage of "thing" interface
38 35 def use(it):
39 36
40 37 # Direct call to base method shared between client and server.
41 38 print(it.hello())
42 39
43 40 # Direct calls to proxied methods. They cause individual roundtrips.
44 41 print(it.foo("Un", two="Deux"))
45 42 print(it.bar("Eins", "Zwei"))
46 43
47 44 # Batched call to a couple of (possibly proxied) methods.
48 45 batch = it.batch()
49 46 # The calls return futures to eventually hold results.
50 47 foo = batch.foo(one="One", two="Two")
51 48 foo2 = batch.foo(None)
52 49 bar = batch.bar("Eins", "Zwei")
53 50 # We can call non-batchable proxy methods, but the break the current batch
54 51 # request and cause additional roundtrips.
55 52 greet = batch.greet(name="John Smith")
56 53 # We can also add local methods into the mix, but they break the batch too.
57 54 hello = batch.hello()
58 55 bar2 = batch.bar(b="Uno", a="Due")
59 56 # Only now are all the calls executed in sequence, with as few roundtrips
60 57 # as possible.
61 58 batch.submit()
62 59 # After the call to submit, the futures actually contain values.
63 60 print(foo.value)
64 61 print(foo2.value)
65 62 print(bar.value)
66 63 print(greet.value)
67 64 print(hello.value)
68 65 print(bar2.value)
69 66
70 67 # local usage
71 68 mylocal = localthing()
72 69 print()
73 70 print("== Local")
74 71 use(mylocal)
75 72
76 73 # demo remoting; mimicks what wireproto and HTTP/SSH do
77 74
78 75 # shared
79 76
80 77 def escapearg(plain):
81 78 return (plain
82 79 .replace(':', '::')
83 80 .replace(',', ':,')
84 81 .replace(';', ':;')
85 82 .replace('=', ':='))
86 83 def unescapearg(escaped):
87 84 return (escaped
88 85 .replace(':=', '=')
89 86 .replace(':;', ';')
90 87 .replace(':,', ',')
91 88 .replace('::', ':'))
92 89
93 90 # server side
94 91
95 92 # equivalent of wireproto's global functions
96 93 class server(object):
97 94 def __init__(self, local):
98 95 self.local = local
99 96 def _call(self, name, args):
100 97 args = dict(arg.split('=', 1) for arg in args)
101 98 return getattr(self, name)(**args)
102 99 def perform(self, req):
103 100 print("REQ:", req)
104 101 name, args = req.split('?', 1)
105 102 args = args.split('&')
106 103 vals = dict(arg.split('=', 1) for arg in args)
107 104 res = getattr(self, name)(**vals)
108 105 print(" ->", res)
109 106 return res
110 107 def batch(self, cmds):
111 108 res = []
112 109 for pair in cmds.split(';'):
113 110 name, args = pair.split(':', 1)
114 111 vals = {}
115 112 for a in args.split(','):
116 113 if a:
117 114 n, v = a.split('=')
118 115 vals[n] = unescapearg(v)
119 116 res.append(escapearg(getattr(self, name)(**vals)))
120 117 return ';'.join(res)
121 118 def foo(self, one, two):
122 119 return mangle(self.local.foo(unmangle(one), unmangle(two)))
123 120 def bar(self, b, a):
124 121 return mangle(self.local.bar(unmangle(b), unmangle(a)))
125 122 def greet(self, name):
126 123 return mangle(self.local.greet(unmangle(name)))
127 124 myserver = server(mylocal)
128 125
129 126 # local side
130 127
131 128 # equivalent of wireproto.encode/decodelist, that is, type-specific marshalling
132 129 # here we just transform the strings a bit to check we're properly en-/decoding
133 130 def mangle(s):
134 131 return ''.join(chr(ord(c) + 1) for c in s)
135 132 def unmangle(s):
136 133 return ''.join(chr(ord(c) - 1) for c in s)
137 134
138 135 # equivalent of wireproto.wirerepository and something like http's wire format
139 136 class remotething(thing):
140 137 def __init__(self, server):
141 138 self.server = server
142 139 def _submitone(self, name, args):
143 140 req = name + '?' + '&'.join(['%s=%s' % (n, v) for n, v in args])
144 141 return self.server.perform(req)
145 142 def _submitbatch(self, cmds):
146 143 req = []
147 144 for name, args in cmds:
148 145 args = ','.join(n + '=' + escapearg(v) for n, v in args)
149 146 req.append(name + ':' + args)
150 147 req = ';'.join(req)
151 148 res = self._submitone('batch', [('cmds', req,)])
152 149 return res.split(';')
153 150
154 151 def batch(self):
155 return remotebatch(self)
152 return wireproto.remotebatch(self)
156 153
157 @batchable
154 @peer.batchable
158 155 def foo(self, one, two=None):
159 156 if not one:
160 157 yield "Nope", None
161 158 encargs = [('one', mangle(one),), ('two', mangle(two),)]
162 encresref = future()
159 encresref = peer.future()
163 160 yield encargs, encresref
164 161 yield unmangle(encresref.value)
165 162
166 @batchable
163 @peer.batchable
167 164 def bar(self, b, a):
168 encresref = future()
165 encresref = peer.future()
169 166 yield [('b', mangle(b),), ('a', mangle(a),)], encresref
170 167 yield unmangle(encresref.value)
171 168
172 169 # greet is coded directly. It therefore does not support batching. If it
173 170 # does appear in a batch, the batch is split around greet, and the call to
174 171 # greet is done in its own roundtrip.
175 172 def greet(self, name=None):
176 173 return unmangle(self._submitone('greet', [('name', mangle(name),)]))
177 174
178 175 # demo remote usage
179 176
180 177 myproxy = remotething(myserver)
181 178 print()
182 179 print("== Remote")
183 180 use(myproxy)
General Comments 0
You need to be logged in to leave comments. Login now