Show More
@@ -26,6 +26,7 b' test-backwards-remove.t' | |||||
26 | test-bad-extension.t |
|
26 | test-bad-extension.t | |
27 | test-bad-pull.t |
|
27 | test-bad-pull.t | |
28 | test-basic.t |
|
28 | test-basic.t | |
|
29 | test-batching.py | |||
29 | test-bdiff.py |
|
30 | test-bdiff.py | |
30 | test-bheads.t |
|
31 | test-bheads.t | |
31 | test-bisect.t |
|
32 | test-bisect.t |
@@ -11,25 +11,28 b' 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): | |
@@ -43,27 +46,27 b' class localthing(thing):' | |||||
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 | |
@@ -72,16 +75,16 b' use(mylocal)' | |||||
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 | |||
@@ -90,27 +93,28 b' 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)( |
|
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): | |
@@ -124,25 +128,25 b' myserver = server(mylocal)' | |||||
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 | |
@@ -155,7 +159,7 b' class remotething(thing):' | |||||
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) | |
@@ -163,18 +167,18 b' class remotething(thing):' | |||||
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) |
General Comments 0
You need to be logged in to leave comments.
Login now