comparison mercurial/pycompat.py @ 38576:152f4822d210

pycompat: move rapply() from util I want to use rapply() in utils.* modules, but that would introduce a reference cycle util -> utils.* -> util. Moving rapply() to pycompat should be okay since it mostly serves as a compatibility helper.
author Yuya Nishihara <yuya@tcha.org>
date Sun, 10 Jun 2018 17:07:29 +0900
parents 7b12a2d2eedc
children 7eba8f83129b
comparison
equal deleted inserted replaced
38575:f442c9494ec7 38576:152f4822d210
44 def future_set_exception_info(f, exc_info): 44 def future_set_exception_info(f, exc_info):
45 f.set_exception(exc_info[0]) 45 f.set_exception(exc_info[0])
46 46
47 def identity(a): 47 def identity(a):
48 return a 48 return a
49
50 def _rapply(f, xs):
51 if xs is None:
52 # assume None means non-value of optional data
53 return xs
54 if isinstance(xs, (list, set, tuple)):
55 return type(xs)(_rapply(f, x) for x in xs)
56 if isinstance(xs, dict):
57 return type(xs)((_rapply(f, k), _rapply(f, v)) for k, v in xs.items())
58 return f(xs)
59
60 def rapply(f, xs):
61 """Apply function recursively to every item preserving the data structure
62
63 >>> def f(x):
64 ... return 'f(%s)' % x
65 >>> rapply(f, None) is None
66 True
67 >>> rapply(f, 'a')
68 'f(a)'
69 >>> rapply(f, {'a'}) == {'f(a)'}
70 True
71 >>> rapply(f, ['a', 'b', None, {'c': 'd'}, []])
72 ['f(a)', 'f(b)', None, {'f(c)': 'f(d)'}, []]
73
74 >>> xs = [object()]
75 >>> rapply(identity, xs) is xs
76 True
77 """
78 if f is identity:
79 # fast path mainly for py2
80 return xs
81 return _rapply(f, xs)
49 82
50 if ispy3: 83 if ispy3:
51 import builtins 84 import builtins
52 import functools 85 import functools
53 import io 86 import io