180 # libraries, and sure enough Mercurial is not a library.) |
180 # libraries, and sure enough Mercurial is not a library.) |
181 os.stat_float_times(False) |
181 os.stat_float_times(False) |
182 |
182 |
183 def safehasattr(thing, attr): |
183 def safehasattr(thing, attr): |
184 return getattr(thing, attr, _notset) is not _notset |
184 return getattr(thing, attr, _notset) is not _notset |
|
185 |
|
186 def _rapply(f, xs): |
|
187 if xs is None: |
|
188 # assume None means non-value of optional data |
|
189 return xs |
|
190 if isinstance(xs, (list, set, tuple)): |
|
191 return type(xs)(_rapply(f, x) for x in xs) |
|
192 if isinstance(xs, dict): |
|
193 return type(xs)((_rapply(f, k), _rapply(f, v)) for k, v in xs.items()) |
|
194 return f(xs) |
|
195 |
|
196 def rapply(f, xs): |
|
197 """Apply function recursively to every item preserving the data structure |
|
198 |
|
199 >>> def f(x): |
|
200 ... return 'f(%s)' % x |
|
201 >>> rapply(f, None) is None |
|
202 True |
|
203 >>> rapply(f, 'a') |
|
204 'f(a)' |
|
205 >>> rapply(f, {'a'}) == {'f(a)'} |
|
206 True |
|
207 >>> rapply(f, ['a', 'b', None, {'c': 'd'}, []]) |
|
208 ['f(a)', 'f(b)', None, {'f(c)': 'f(d)'}, []] |
|
209 |
|
210 >>> xs = [object()] |
|
211 >>> rapply(pycompat.identity, xs) is xs |
|
212 True |
|
213 """ |
|
214 if f is pycompat.identity: |
|
215 # fast path mainly for py2 |
|
216 return xs |
|
217 return _rapply(f, xs) |
185 |
218 |
186 def bytesinput(fin, fout, *args, **kwargs): |
219 def bytesinput(fin, fout, *args, **kwargs): |
187 sin, sout = sys.stdin, sys.stdout |
220 sin, sout = sys.stdin, sys.stdout |
188 try: |
221 try: |
189 sys.stdin, sys.stdout = encoding.strio(fin), encoding.strio(fout) |
222 sys.stdin, sys.stdout = encoding.strio(fin), encoding.strio(fout) |