Mercurial > hg
comparison tests/test-batching.py @ 41335:b81ca9a3f4e4
py3: port test-batching.py to python3
I used byteify-strings.py on this file, then manually added the
various pycompat and bprint bits as needed.
Differential Revision: https://phab.mercurial-scm.org/D5678
author | Augie Fackler <augie@google.com> |
---|---|
date | Thu, 24 Jan 2019 11:35:40 -0500 |
parents | 33a6eee08db2 |
children | 2372284d9457 |
comparison
equal
deleted
inserted
replaced
41334:5361f9ed8a30 | 41335:b81ca9a3f4e4 |
---|---|
9 | 9 |
10 import contextlib | 10 import contextlib |
11 | 11 |
12 from mercurial import ( | 12 from mercurial import ( |
13 localrepo, | 13 localrepo, |
14 pycompat, | |
14 wireprotov1peer, | 15 wireprotov1peer, |
16 ) | |
15 | 17 |
16 ) | 18 def bprint(*bs): |
19 print(*[pycompat.sysstr(b) for b in bs]) | |
17 | 20 |
18 # equivalent of repo.repository | 21 # equivalent of repo.repository |
19 class thing(object): | 22 class thing(object): |
20 def hello(self): | 23 def hello(self): |
21 return "Ready." | 24 return b"Ready." |
22 | 25 |
23 # equivalent of localrepo.localrepository | 26 # equivalent of localrepo.localrepository |
24 class localthing(thing): | 27 class localthing(thing): |
25 def foo(self, one, two=None): | 28 def foo(self, one, two=None): |
26 if one: | 29 if one: |
27 return "%s and %s" % (one, two,) | 30 return b"%s and %s" % (one, two,) |
28 return "Nope" | 31 return b"Nope" |
29 def bar(self, b, a): | 32 def bar(self, b, a): |
30 return "%s und %s" % (b, a,) | 33 return b"%s und %s" % (b, a,) |
31 def greet(self, name=None): | 34 def greet(self, name=None): |
32 return "Hello, %s" % name | 35 return b"Hello, %s" % name |
33 | 36 |
34 @contextlib.contextmanager | 37 @contextlib.contextmanager |
35 def commandexecutor(self): | 38 def commandexecutor(self): |
36 e = localrepo.localcommandexecutor(self) | 39 e = localrepo.localcommandexecutor(self) |
37 try: | 40 try: |
41 | 44 |
42 # usage of "thing" interface | 45 # usage of "thing" interface |
43 def use(it): | 46 def use(it): |
44 | 47 |
45 # Direct call to base method shared between client and server. | 48 # Direct call to base method shared between client and server. |
46 print(it.hello()) | 49 bprint(it.hello()) |
47 | 50 |
48 # Direct calls to proxied methods. They cause individual roundtrips. | 51 # Direct calls to proxied methods. They cause individual roundtrips. |
49 print(it.foo("Un", two="Deux")) | 52 bprint(it.foo(b"Un", two=b"Deux")) |
50 print(it.bar("Eins", "Zwei")) | 53 bprint(it.bar(b"Eins", b"Zwei")) |
51 | 54 |
52 # Batched call to a couple of proxied methods. | 55 # Batched call to a couple of proxied methods. |
53 | 56 |
54 with it.commandexecutor() as e: | 57 with it.commandexecutor() as e: |
55 ffoo = e.callcommand('foo', {'one': 'One', 'two': 'Two'}) | 58 ffoo = e.callcommand(b'foo', {b'one': b'One', b'two': b'Two'}) |
56 fbar = e.callcommand('bar', {'b': 'Eins', 'a': 'Zwei'}) | 59 fbar = e.callcommand(b'bar', {b'b': b'Eins', b'a': b'Zwei'}) |
57 fbar2 = e.callcommand('bar', {'b': 'Uno', 'a': 'Due'}) | 60 fbar2 = e.callcommand(b'bar', {b'b': b'Uno', b'a': b'Due'}) |
58 | 61 |
59 print(ffoo.result()) | 62 bprint(ffoo.result()) |
60 print(fbar.result()) | 63 bprint(fbar.result()) |
61 print(fbar2.result()) | 64 bprint(fbar2.result()) |
62 | 65 |
63 # local usage | 66 # local usage |
64 mylocal = localthing() | 67 mylocal = localthing() |
65 print() | 68 print() |
66 print("== Local") | 69 bprint(b"== Local") |
67 use(mylocal) | 70 use(mylocal) |
68 | 71 |
69 # demo remoting; mimicks what wireproto and HTTP/SSH do | 72 # demo remoting; mimicks what wireproto and HTTP/SSH do |
70 | 73 |
71 # shared | 74 # shared |
72 | 75 |
73 def escapearg(plain): | 76 def escapearg(plain): |
74 return (plain | 77 return (plain |
75 .replace(':', '::') | 78 .replace(b':', b'::') |
76 .replace(',', ':,') | 79 .replace(b',', b':,') |
77 .replace(';', ':;') | 80 .replace(b';', b':;') |
78 .replace('=', ':=')) | 81 .replace(b'=', b':=')) |
79 def unescapearg(escaped): | 82 def unescapearg(escaped): |
80 return (escaped | 83 return (escaped |
81 .replace(':=', '=') | 84 .replace(b':=', b'=') |
82 .replace(':;', ';') | 85 .replace(b':;', b';') |
83 .replace(':,', ',') | 86 .replace(b':,', b',') |
84 .replace('::', ':')) | 87 .replace(b'::', b':')) |
85 | 88 |
86 # server side | 89 # server side |
87 | 90 |
88 # equivalent of wireproto's global functions | 91 # equivalent of wireproto's global functions |
89 class server(object): | 92 class server(object): |
90 def __init__(self, local): | 93 def __init__(self, local): |
91 self.local = local | 94 self.local = local |
92 def _call(self, name, args): | 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 return getattr(self, name)(**args) | 97 return getattr(self, name)(**args) |
95 def perform(self, req): | 98 def perform(self, req): |
96 print("REQ:", req) | 99 bprint(b"REQ:", req) |
97 name, args = req.split('?', 1) | 100 name, args = req.split(b'?', 1) |
98 args = args.split('&') | 101 args = args.split(b'&') |
99 vals = dict(arg.split('=', 1) for arg in args) | 102 vals = dict(arg.split(b'=', 1) for arg in args) |
100 res = getattr(self, name)(**vals) | 103 res = getattr(self, pycompat.sysstr(name))(**pycompat.strkwargs(vals)) |
101 print(" ->", res) | 104 bprint(b" ->", res) |
102 return res | 105 return res |
103 def batch(self, cmds): | 106 def batch(self, cmds): |
104 res = [] | 107 res = [] |
105 for pair in cmds.split(';'): | 108 for pair in cmds.split(b';'): |
106 name, args = pair.split(':', 1) | 109 name, args = pair.split(b':', 1) |
107 vals = {} | 110 vals = {} |
108 for a in args.split(','): | 111 for a in args.split(b','): |
109 if a: | 112 if a: |
110 n, v = a.split('=') | 113 n, v = a.split(b'=') |
111 vals[n] = unescapearg(v) | 114 vals[n] = unescapearg(v) |
112 res.append(escapearg(getattr(self, name)(**vals))) | 115 res.append(escapearg(getattr(self, pycompat.sysstr(name))( |
113 return ';'.join(res) | 116 **pycompat.strkwargs(vals)))) |
117 return b';'.join(res) | |
114 def foo(self, one, two): | 118 def foo(self, one, two): |
115 return mangle(self.local.foo(unmangle(one), unmangle(two))) | 119 return mangle(self.local.foo(unmangle(one), unmangle(two))) |
116 def bar(self, b, a): | 120 def bar(self, b, a): |
117 return mangle(self.local.bar(unmangle(b), unmangle(a))) | 121 return mangle(self.local.bar(unmangle(b), unmangle(a))) |
118 def greet(self, name): | 122 def greet(self, name): |
122 # local side | 126 # local side |
123 | 127 |
124 # equivalent of wireproto.encode/decodelist, that is, type-specific marshalling | 128 # equivalent of wireproto.encode/decodelist, that is, type-specific marshalling |
125 # here we just transform the strings a bit to check we're properly en-/decoding | 129 # here we just transform the strings a bit to check we're properly en-/decoding |
126 def mangle(s): | 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 def unmangle(s): | 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 # equivalent of wireproto.wirerepository and something like http's wire format | 135 # equivalent of wireproto.wirerepository and something like http's wire format |
132 class remotething(thing): | 136 class remotething(thing): |
133 def __init__(self, server): | 137 def __init__(self, server): |
134 self.server = server | 138 self.server = server |
135 def _submitone(self, name, args): | 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 return self.server.perform(req) | 141 return self.server.perform(req) |
138 def _submitbatch(self, cmds): | 142 def _submitbatch(self, cmds): |
139 req = [] | 143 req = [] |
140 for name, args in cmds: | 144 for name, args in cmds: |
141 args = ','.join(n + '=' + escapearg(v) for n, v in args) | 145 args = b','.join(n + b'=' + escapearg(v) for n, v in args) |
142 req.append(name + ':' + args) | 146 req.append(name + b':' + args) |
143 req = ';'.join(req) | 147 req = b';'.join(req) |
144 res = self._submitone('batch', [('cmds', req,)]) | 148 res = self._submitone(b'batch', [(b'cmds', req,)]) |
145 for r in res.split(';'): | 149 for r in res.split(b';'): |
146 yield r | 150 yield r |
147 | 151 |
148 @contextlib.contextmanager | 152 @contextlib.contextmanager |
149 def commandexecutor(self): | 153 def commandexecutor(self): |
150 e = wireprotov1peer.peerexecutor(self) | 154 e = wireprotov1peer.peerexecutor(self) |
153 finally: | 157 finally: |
154 e.close() | 158 e.close() |
155 | 159 |
156 @wireprotov1peer.batchable | 160 @wireprotov1peer.batchable |
157 def foo(self, one, two=None): | 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 encresref = wireprotov1peer.future() | 163 encresref = wireprotov1peer.future() |
160 yield encargs, encresref | 164 yield encargs, encresref |
161 yield unmangle(encresref.value) | 165 yield unmangle(encresref.value) |
162 | 166 |
163 @wireprotov1peer.batchable | 167 @wireprotov1peer.batchable |
164 def bar(self, b, a): | 168 def bar(self, b, a): |
165 encresref = wireprotov1peer.future() | 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 yield unmangle(encresref.value) | 171 yield unmangle(encresref.value) |
168 | 172 |
169 # greet is coded directly. It therefore does not support batching. If it | 173 # greet is coded directly. It therefore does not support batching. If it |
170 # does appear in a batch, the batch is split around greet, and the call to | 174 # does appear in a batch, the batch is split around greet, and the call to |
171 # greet is done in its own roundtrip. | 175 # greet is done in its own roundtrip. |
172 def greet(self, name=None): | 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 # demo remote usage | 179 # demo remote usage |
176 | 180 |
177 myproxy = remotething(myserver) | 181 myproxy = remotething(myserver) |
178 print() | 182 print() |
179 print("== Remote") | 183 bprint(b"== Remote") |
180 use(myproxy) | 184 use(myproxy) |