--- a/mercurial/pycompat.py Thu Jul 05 09:53:00 2018 +0530
+++ b/mercurial/pycompat.py Sun Jun 10 17:07:29 2018 +0900
@@ -47,6 +47,39 @@
def identity(a):
return a
+def _rapply(f, xs):
+ if xs is None:
+ # assume None means non-value of optional data
+ return xs
+ if isinstance(xs, (list, set, tuple)):
+ return type(xs)(_rapply(f, x) for x in xs)
+ if isinstance(xs, dict):
+ return type(xs)((_rapply(f, k), _rapply(f, v)) for k, v in xs.items())
+ return f(xs)
+
+def rapply(f, xs):
+ """Apply function recursively to every item preserving the data structure
+
+ >>> def f(x):
+ ... return 'f(%s)' % x
+ >>> rapply(f, None) is None
+ True
+ >>> rapply(f, 'a')
+ 'f(a)'
+ >>> rapply(f, {'a'}) == {'f(a)'}
+ True
+ >>> rapply(f, ['a', 'b', None, {'c': 'd'}, []])
+ ['f(a)', 'f(b)', None, {'f(c)': 'f(d)'}, []]
+
+ >>> xs = [object()]
+ >>> rapply(identity, xs) is xs
+ True
+ """
+ if f is identity:
+ # fast path mainly for py2
+ return xs
+ return _rapply(f, xs)
+
if ispy3:
import builtins
import functools