##// END OF EJS Templates
lfs: don't require the .hglfs file to be tracked to control the policy...
lfs: don't require the .hglfs file to be tracked to control the policy The .hgignore file doesn't need to be tracked, nor does the git equivalent of this file. I'm still a little concerned about the effects of forgetting to commit this file. But the fact that conversions maintain the hashes if only the normal vs external storage changes, should make this less risky.

File last commit:

r33761:4c706037 default
r35825:4425790f stable
Show More
test-batching.py
206 lines | 6.0 KiB | text/x-python | PythonLexer
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 # test-batching.py - tests for transparent command batching
#
# Copyright 2011 Peter Arrenbrecht <peter@arrenbrecht.ch>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
Robert Stanca
py3: use print_function in test-batching.py
r28732 from __future__ import absolute_import, print_function
Yuya Nishihara
test-batching: stop direct symbol import of mercurial modules...
r28800
from mercurial import (
Gregory Szorc
wireproto: overhaul iterating batcher code (API)...
r33761 error,
Yuya Nishihara
test-batching: stop direct symbol import of mercurial modules...
r28800 peer,
Gregory Szorc
wireproto: overhaul iterating batcher code (API)...
r33761 util,
Yuya Nishihara
test-batching: stop direct symbol import of mercurial modules...
r28800 wireproto,
Robert Stanca
py3: use absolute_import in test-batching.py
r28731 )
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621
# equivalent of repo.repository
class thing(object):
def hello(self):
return "Ready."
# equivalent of localrepo.localrepository
class localthing(thing):
def foo(self, one, two=None):
if one:
return "%s and %s" % (one, two,)
return "Nope"
def bar(self, b, a):
return "%s und %s" % (b, a,)
def greet(self, name=None):
return "Hello, %s" % name
Gregory Szorc
wireproto: overhaul iterating batcher code (API)...
r33761 def batchiter(self):
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 '''Support for local batching.'''
Gregory Szorc
wireproto: overhaul iterating batcher code (API)...
r33761 return peer.localiterbatcher(self)
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621
# usage of "thing" interface
def use(it):
# Direct call to base method shared between client and server.
Robert Stanca
py3: use print_function in test-batching.py
r28732 print(it.hello())
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621
# Direct calls to proxied methods. They cause individual roundtrips.
Robert Stanca
py3: use print_function in test-batching.py
r28732 print(it.foo("Un", two="Deux"))
print(it.bar("Eins", "Zwei"))
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621
Gregory Szorc
wireproto: overhaul iterating batcher code (API)...
r33761 # Batched call to a couple of proxied methods.
batch = it.batchiter()
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 # The calls return futures to eventually hold results.
foo = batch.foo(one="One", two="Two")
bar = batch.bar("Eins", "Zwei")
bar2 = batch.bar(b="Uno", a="Due")
Gregory Szorc
wireproto: overhaul iterating batcher code (API)...
r33761
# Future shouldn't be set until we submit().
assert isinstance(foo, peer.future)
assert not util.safehasattr(foo, 'value')
assert not util.safehasattr(bar, 'value')
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 batch.submit()
Gregory Szorc
wireproto: overhaul iterating batcher code (API)...
r33761 # Call results() to obtain results as a generator.
results = batch.results()
# Future results shouldn't be set until we consume a value.
assert not util.safehasattr(foo, 'value')
foovalue = next(results)
assert util.safehasattr(foo, 'value')
assert foovalue == foo.value
Robert Stanca
py3: use print_function in test-batching.py
r28732 print(foo.value)
Gregory Szorc
wireproto: overhaul iterating batcher code (API)...
r33761 next(results)
Robert Stanca
py3: use print_function in test-batching.py
r28732 print(bar.value)
Gregory Szorc
wireproto: overhaul iterating batcher code (API)...
r33761 next(results)
Robert Stanca
py3: use print_function in test-batching.py
r28732 print(bar2.value)
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621
Gregory Szorc
wireproto: overhaul iterating batcher code (API)...
r33761 # We should be at the end of the results generator.
try:
next(results)
except StopIteration:
print('proper end of results generator')
else:
print('extra emitted element!')
# Attempting to call a non-batchable method inside a batch fails.
batch = it.batchiter()
try:
batch.greet(name='John Smith')
except error.ProgrammingError as e:
print(e)
# Attempting to call a local method inside a batch fails.
batch = it.batchiter()
try:
batch.hello()
except error.ProgrammingError as e:
print(e)
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 # local usage
mylocal = localthing()
Robert Stanca
py3: use print_function in test-batching.py
r28732 print()
print("== Local")
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 use(mylocal)
# demo remoting; mimicks what wireproto and HTTP/SSH do
# shared
def escapearg(plain):
return (plain
.replace(':', '::')
.replace(',', ':,')
.replace(';', ':;')
.replace('=', ':='))
def unescapearg(escaped):
return (escaped
.replace(':=', '=')
.replace(':;', ';')
.replace(':,', ',')
.replace('::', ':'))
# server side
# equivalent of wireproto's global functions
Thomas Arendsen Hein
classes: fix class style problems found by b071cd58af50...
r14764 class server(object):
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 def __init__(self, local):
self.local = local
def _call(self, name, args):
args = dict(arg.split('=', 1) for arg in args)
return getattr(self, name)(**args)
def perform(self, req):
Robert Stanca
py3: use print_function in test-batching.py
r28732 print("REQ:", req)
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 name, args = req.split('?', 1)
args = args.split('&')
vals = dict(arg.split('=', 1) for arg in args)
res = getattr(self, name)(**vals)
Robert Stanca
py3: use print_function in test-batching.py
r28732 print(" ->", res)
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 return res
def batch(self, cmds):
res = []
for pair in cmds.split(';'):
name, args = pair.split(':', 1)
vals = {}
for a in args.split(','):
if a:
n, v = a.split('=')
vals[n] = unescapearg(v)
res.append(escapearg(getattr(self, name)(**vals)))
return ';'.join(res)
def foo(self, one, two):
return mangle(self.local.foo(unmangle(one), unmangle(two)))
def bar(self, b, a):
return mangle(self.local.bar(unmangle(b), unmangle(a)))
def greet(self, name):
return mangle(self.local.greet(unmangle(name)))
myserver = server(mylocal)
# local side
# equivalent of wireproto.encode/decodelist, that is, type-specific marshalling
# here we just transform the strings a bit to check we're properly en-/decoding
def mangle(s):
return ''.join(chr(ord(c) + 1) for c in s)
def unmangle(s):
return ''.join(chr(ord(c) - 1) for c in s)
# equivalent of wireproto.wirerepository and something like http's wire format
class remotething(thing):
def __init__(self, server):
self.server = server
def _submitone(self, name, args):
req = name + '?' + '&'.join(['%s=%s' % (n, v) for n, v in args])
return self.server.perform(req)
def _submitbatch(self, cmds):
req = []
for name, args in cmds:
args = ','.join(n + '=' + escapearg(v) for n, v in args)
req.append(name + ':' + args)
req = ';'.join(req)
res = self._submitone('batch', [('cmds', req,)])
Gregory Szorc
wireproto: overhaul iterating batcher code (API)...
r33761 for r in res.split(';'):
yield r
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621
Gregory Szorc
wireproto: overhaul iterating batcher code (API)...
r33761 def batchiter(self):
return wireproto.remoteiterbatcher(self)
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621
Yuya Nishihara
test-batching: stop direct symbol import of mercurial modules...
r28800 @peer.batchable
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 def foo(self, one, two=None):
encargs = [('one', mangle(one),), ('two', mangle(two),)]
Yuya Nishihara
test-batching: stop direct symbol import of mercurial modules...
r28800 encresref = peer.future()
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 yield encargs, encresref
yield unmangle(encresref.value)
Yuya Nishihara
test-batching: stop direct symbol import of mercurial modules...
r28800 @peer.batchable
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 def bar(self, b, a):
Yuya Nishihara
test-batching: stop direct symbol import of mercurial modules...
r28800 encresref = peer.future()
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 yield [('b', mangle(b),), ('a', mangle(a),)], encresref
yield unmangle(encresref.value)
# greet is coded directly. It therefore does not support batching. If it
# does appear in a batch, the batch is split around greet, and the call to
# greet is done in its own roundtrip.
def greet(self, name=None):
return unmangle(self._submitone('greet', [('name', mangle(name),)]))
# demo remote usage
myproxy = remotething(myserver)
Robert Stanca
py3: use print_function in test-batching.py
r28732 print()
print("== Remote")
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 use(myproxy)