obsolete: store user name and note in UTF-8 (issue5754) (BC)
Before, user names were stored in local encoding and transferred across
repositories, which made it impossible to restore non-ASCII user names on
different platforms. This patch fixes new markers to be encoded in UTF-8
and decoded back to local encoding when displaying. Existing markers are
unfixable so they may result in mojibake.
I don't like the API that requires metadata dict to be UTF-8 encoded, which
is a source of bugs, but there's no abstraction layer to process the encoding
thingy efficiently. So we apply the same rule as extras dict to obsstore
metadata.
from __future__ import absolute_import, print_function
from mercurial import extensions
def genwrapper(x):
def f(orig, *args, **kwds):
return [x] + orig(*args, **kwds)
f.x = x
return f
def getid(wrapper):
return getattr(wrapper, 'x', '-')
wrappers = [genwrapper(i) for i in range(5)]
class dummyclass(object):
def getstack(self):
return ['orig']
dummy = dummyclass()
def batchwrap(wrappers):
for w in wrappers:
extensions.wrapfunction(dummy, 'getstack', w)
print('wrap %d: %s' % (getid(w), dummy.getstack()))
def batchunwrap(wrappers):
for w in wrappers:
result = None
try:
result = extensions.unwrapfunction(dummy, 'getstack', w)
msg = str(dummy.getstack())
except (ValueError, IndexError) as e:
msg = e.__class__.__name__
print('unwrap %s: %s: %s' % (getid(w), getid(result), msg))
batchwrap(wrappers + [wrappers[0]])
batchunwrap([(wrappers[i] if i is not None and i >= 0 else None)
for i in [3, None, 0, 4, 0, 2, 1, None]])
wrap0 = extensions.wrappedfunction(dummy, 'getstack', wrappers[0])
wrap1 = extensions.wrappedfunction(dummy, 'getstack', wrappers[1])
# Use them in a different order from how they were created to check that
# the wrapping happens in __enter__, not in __init__
print('context manager', dummy.getstack())
with wrap1:
print('context manager', dummy.getstack())
with wrap0:
print('context manager', dummy.getstack())
# Bad programmer forgets to unwrap the function, but the context
# managers still unwrap their wrappings.
extensions.wrapfunction(dummy, 'getstack', wrappers[2])
print('context manager', dummy.getstack())
print('context manager', dummy.getstack())
print('context manager', dummy.getstack())
# Wrap callable object which has no __name__
class callableobj(object):
def __call__(self):
return ['orig']
dummy.cobj = callableobj()
extensions.wrapfunction(dummy, 'cobj', wrappers[0])
print('wrap callable object', dummy.cobj())