##// END OF EJS Templates
py3: port test-batching.py to python3...
Augie Fackler -
r41366:b81ca9a3 default
parent child Browse files
Show More
@@ -26,6 +26,7 b' test-backwards-remove.t'
26 26 test-bad-extension.t
27 27 test-bad-pull.t
28 28 test-basic.t
29 test-batching.py
29 30 test-bdiff.py
30 31 test-bheads.t
31 32 test-bisect.t
@@ -11,25 +11,28 b' import contextlib'
11 11
12 12 from mercurial import (
13 13 localrepo,
14 pycompat,
14 15 wireprotov1peer,
16 )
15 17
16 )
18 def bprint(*bs):
19 print(*[pycompat.sysstr(b) for b in bs])
17 20
18 21 # equivalent of repo.repository
19 22 class thing(object):
20 23 def hello(self):
21 return "Ready."
24 return b"Ready."
22 25
23 26 # equivalent of localrepo.localrepository
24 27 class localthing(thing):
25 28 def foo(self, one, two=None):
26 29 if one:
27 return "%s and %s" % (one, two,)
28 return "Nope"
30 return b"%s and %s" % (one, two,)
31 return b"Nope"
29 32 def bar(self, b, a):
30 return "%s und %s" % (b, a,)
33 return b"%s und %s" % (b, a,)
31 34 def greet(self, name=None):
32 return "Hello, %s" % name
35 return b"Hello, %s" % name
33 36
34 37 @contextlib.contextmanager
35 38 def commandexecutor(self):
@@ -43,27 +46,27 b' class localthing(thing):'
43 46 def use(it):
44 47
45 48 # Direct call to base method shared between client and server.
46 print(it.hello())
49 bprint(it.hello())
47 50
48 51 # Direct calls to proxied methods. They cause individual roundtrips.
49 print(it.foo("Un", two="Deux"))
50 print(it.bar("Eins", "Zwei"))
52 bprint(it.foo(b"Un", two=b"Deux"))
53 bprint(it.bar(b"Eins", b"Zwei"))
51 54
52 55 # Batched call to a couple of proxied methods.
53 56
54 57 with it.commandexecutor() as e:
55 ffoo = e.callcommand('foo', {'one': 'One', 'two': 'Two'})
56 fbar = e.callcommand('bar', {'b': 'Eins', 'a': 'Zwei'})
57 fbar2 = e.callcommand('bar', {'b': 'Uno', 'a': 'Due'})
58 ffoo = e.callcommand(b'foo', {b'one': b'One', b'two': b'Two'})
59 fbar = e.callcommand(b'bar', {b'b': b'Eins', b'a': b'Zwei'})
60 fbar2 = e.callcommand(b'bar', {b'b': b'Uno', b'a': b'Due'})
58 61
59 print(ffoo.result())
60 print(fbar.result())
61 print(fbar2.result())
62 bprint(ffoo.result())
63 bprint(fbar.result())
64 bprint(fbar2.result())
62 65
63 66 # local usage
64 67 mylocal = localthing()
65 68 print()
66 print("== Local")
69 bprint(b"== Local")
67 70 use(mylocal)
68 71
69 72 # demo remoting; mimicks what wireproto and HTTP/SSH do
@@ -72,16 +75,16 b' use(mylocal)'
72 75
73 76 def escapearg(plain):
74 77 return (plain
75 .replace(':', '::')
76 .replace(',', ':,')
77 .replace(';', ':;')
78 .replace('=', ':='))
78 .replace(b':', b'::')
79 .replace(b',', b':,')
80 .replace(b';', b':;')
81 .replace(b'=', b':='))
79 82 def unescapearg(escaped):
80 83 return (escaped
81 .replace(':=', '=')
82 .replace(':;', ';')
83 .replace(':,', ',')
84 .replace('::', ':'))
84 .replace(b':=', b'=')
85 .replace(b':;', b';')
86 .replace(b':,', b',')
87 .replace(b'::', b':'))
85 88
86 89 # server side
87 90
@@ -90,27 +93,28 b' class server(object):'
90 93 def __init__(self, local):
91 94 self.local = local
92 95 def _call(self, name, args):
93 args = dict(arg.split('=', 1) for arg in args)
96 args = dict(arg.split(b'=', 1) for arg in args)
94 97 return getattr(self, name)(**args)
95 98 def perform(self, req):
96 print("REQ:", req)
97 name, args = req.split('?', 1)
98 args = args.split('&')
99 vals = dict(arg.split('=', 1) for arg in args)
100 res = getattr(self, name)(**vals)
101 print(" ->", res)
99 bprint(b"REQ:", req)
100 name, args = req.split(b'?', 1)
101 args = args.split(b'&')
102 vals = dict(arg.split(b'=', 1) for arg in args)
103 res = getattr(self, pycompat.sysstr(name))(**pycompat.strkwargs(vals))
104 bprint(b" ->", res)
102 105 return res
103 106 def batch(self, cmds):
104 107 res = []
105 for pair in cmds.split(';'):
106 name, args = pair.split(':', 1)
108 for pair in cmds.split(b';'):
109 name, args = pair.split(b':', 1)
107 110 vals = {}
108 for a in args.split(','):
111 for a in args.split(b','):
109 112 if a:
110 n, v = a.split('=')
113 n, v = a.split(b'=')
111 114 vals[n] = unescapearg(v)
112 res.append(escapearg(getattr(self, name)(**vals)))
113 return ';'.join(res)
115 res.append(escapearg(getattr(self, pycompat.sysstr(name))(
116 **pycompat.strkwargs(vals))))
117 return b';'.join(res)
114 118 def foo(self, one, two):
115 119 return mangle(self.local.foo(unmangle(one), unmangle(two)))
116 120 def bar(self, b, a):
@@ -124,25 +128,25 b' myserver = server(mylocal)'
124 128 # equivalent of wireproto.encode/decodelist, that is, type-specific marshalling
125 129 # here we just transform the strings a bit to check we're properly en-/decoding
126 130 def mangle(s):
127 return ''.join(chr(ord(c) + 1) for c in s)
131 return b''.join(pycompat.bytechr(ord(c) + 1) for c in pycompat.bytestr(s))
128 132 def unmangle(s):
129 return ''.join(chr(ord(c) - 1) for c in s)
133 return b''.join(pycompat.bytechr(ord(c) - 1) for c in pycompat.bytestr(s))
130 134
131 135 # equivalent of wireproto.wirerepository and something like http's wire format
132 136 class remotething(thing):
133 137 def __init__(self, server):
134 138 self.server = server
135 139 def _submitone(self, name, args):
136 req = name + '?' + '&'.join(['%s=%s' % (n, v) for n, v in args])
140 req = name + b'?' + b'&'.join([b'%s=%s' % (n, v) for n, v in args])
137 141 return self.server.perform(req)
138 142 def _submitbatch(self, cmds):
139 143 req = []
140 144 for name, args in cmds:
141 args = ','.join(n + '=' + escapearg(v) for n, v in args)
142 req.append(name + ':' + args)
143 req = ';'.join(req)
144 res = self._submitone('batch', [('cmds', req,)])
145 for r in res.split(';'):
145 args = b','.join(n + b'=' + escapearg(v) for n, v in args)
146 req.append(name + b':' + args)
147 req = b';'.join(req)
148 res = self._submitone(b'batch', [(b'cmds', req,)])
149 for r in res.split(b';'):
146 150 yield r
147 151
148 152 @contextlib.contextmanager
@@ -155,7 +159,7 b' class remotething(thing):'
155 159
156 160 @wireprotov1peer.batchable
157 161 def foo(self, one, two=None):
158 encargs = [('one', mangle(one),), ('two', mangle(two),)]
162 encargs = [(b'one', mangle(one),), (b'two', mangle(two),)]
159 163 encresref = wireprotov1peer.future()
160 164 yield encargs, encresref
161 165 yield unmangle(encresref.value)
@@ -163,18 +167,18 b' class remotething(thing):'
163 167 @wireprotov1peer.batchable
164 168 def bar(self, b, a):
165 169 encresref = wireprotov1peer.future()
166 yield [('b', mangle(b),), ('a', mangle(a),)], encresref
170 yield [(b'b', mangle(b),), (b'a', mangle(a),)], encresref
167 171 yield unmangle(encresref.value)
168 172
169 173 # greet is coded directly. It therefore does not support batching. If it
170 174 # does appear in a batch, the batch is split around greet, and the call to
171 175 # greet is done in its own roundtrip.
172 176 def greet(self, name=None):
173 return unmangle(self._submitone('greet', [('name', mangle(name),)]))
177 return unmangle(self._submitone(b'greet', [(b'name', mangle(name),)]))
174 178
175 179 # demo remote usage
176 180
177 181 myproxy = remotething(myserver)
178 182 print()
179 print("== Remote")
183 bprint(b"== Remote")
180 184 use(myproxy)
General Comments 0
You need to be logged in to leave comments. Login now