19
19
# along with duplicity; if not, write to the Free Software Foundation,
20
20
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
"""Define some lazy data structures and functions acting on them"""
22
u"""Define some lazy data structures and functions acting on them"""
23
23
from __future__ import print_function
32
"""Hold static methods for the manipulation of lazy iterators"""
32
u"""Hold static methods for the manipulation of lazy iterators"""
35
35
def filter(predicate, iterator): # @NoSelf
36
"""Like filter in a lazy functional programming language"""
36
u"""Like filter in a lazy functional programming language"""
42
42
def map(function, iterator): # @NoSelf
43
"""Like map in a lazy functional programming language"""
43
u"""Like map in a lazy functional programming language"""
48
48
def foreach(function, iterator): # @NoSelf
49
"""Run function on each element in iterator"""
49
u"""Run function on each element in iterator"""
54
54
def cat(*iters): # @NoSelf
55
"""Lazily concatenate iterators"""
55
u"""Lazily concatenate iterators"""
61
61
def cat2(iter_of_iters): # @NoSelf
62
"""Lazily concatenate iterators, iterated by big iterator"""
62
u"""Lazily concatenate iterators, iterated by big iterator"""
63
63
for iter in iter_of_iters:
68
68
def empty(iter): # @NoSelf
69
"""True if iterator has length 0"""
69
u"""True if iterator has length 0"""
70
70
for i in iter: # @UnusedVariable
75
75
def equal(iter1, iter2, verbose=None, operator=lambda x, y: x == y): # @NoSelf
76
"""True if iterator 1 has same elements as iterator 2
76
u"""True if iterator 1 has same elements as iterator 2
78
78
Use equality operator, or == if it is unspecified.
84
84
except StopIteration:
86
print("End when i1 = %s" % (i1,))
86
print(u"End when i1 = %s" % (i1,))
88
88
if not operator(i1, i2):
90
print("%s not equal to %s" % (i1, i2))
90
print(u"%s not equal to %s" % (i1, i2))
94
94
except StopIteration:
97
print("End when i2 = %s" % (i2,))
97
print(u"End when i2 = %s" % (i2,))
101
101
def Or(iter): # @NoSelf
102
"""True if any element in iterator is true. Short circuiting"""
102
u"""True if any element in iterator is true. Short circuiting"""
149
149
def multiplex(iter, num_of_forks, final_func=None, closing_func=None): # @NoSelf
150
"""Split a single iterater into a number of streams
150
u"""Split a single iterater into a number of streams
152
152
The return val will be a list with length num_of_forks, each
153
153
of which will be an iterator like iter. final_func is the
175
175
called_closing_func = [None]
177
177
def get_next(fork_num):
178
"""Return the next element requested by fork_num"""
178
u"""Return the next element requested by fork_num"""
179
179
if forkposition[fork_num] == -1:
181
181
buffer.insert(0, next(iter))
210
210
class IterMultiplex2:
211
"""Multiplex an iterator into 2 parts
211
u"""Multiplex an iterator into 2 parts
213
213
This is a special optimized case of the Iter.multiplex function,
214
214
used when there is no closing_func or final_func, and we only want
223
223
def yielda(self):
224
"""Return first iterator"""
224
u"""Return first iterator"""
225
225
buf, iter = self.buffer, self.iter
227
227
if self.a_leading_by >= 0:
237
237
def yieldb(self):
238
"""Return second iterator"""
238
u"""Return second iterator"""
239
239
buf, iter = self.buffer, self.iter
241
241
if self.a_leading_by <= 0:
252
252
class IterTreeReducer:
253
"""Tree style reducer object for iterator - stolen from rdiff-backup
253
u"""Tree style reducer object for iterator - stolen from rdiff-backup
255
255
The indicies of a RORPIter form a tree type structure. This class
256
256
can be used on each element of an iter in sequence and the result
272
272
self.branches = [self.root_branch]
274
274
def finish_branches(self, index):
275
"""Run Finish() on all branches index has passed
275
u"""Run Finish() on all branches index has passed
277
277
When we pass out of a branch, delete it and process it with
278
278
the parent. The innermost branches will be the last in the
297
297
def add_branch(self):
298
"""Return branch of type self.branch_class, add to branch list"""
298
u"""Return branch of type self.branch_class, add to branch list"""
299
299
branch = self.branch_class(*self.branch_args)
300
300
self.branches.append(branch)
303
303
def process_w_branch(self, index, branch, args):
304
"""Run start_process on latest branch"""
304
u"""Run start_process on latest branch"""
305
305
robust.check_common_error(branch.on_error,
306
306
branch.start_process, args)
307
307
if not branch.caught_exception:
309
309
branch.base_index = index
311
311
def Finish(self):
312
"""Call at end of sequence to tie everything up"""
312
u"""Call at end of sequence to tie everything up"""
314
314
to_be_finished = self.branches.pop()
315
315
to_be_finished.call_end_proc()
318
318
self.branches[-1].branch_process(to_be_finished)
320
320
def __call__(self, *args):
321
"""Process args, where args[0] is current position in iterator
321
u"""Process args, where args[0] is current position in iterator
323
323
Returns true if args successfully processed, false if index is
324
324
not in the current tree and thus the final result is
360
"""Helper class for IterTreeReducer above
360
u"""Helper class for IterTreeReducer above
362
362
There are five stub functions below: start_process, end_process,
363
363
branch_process, fast_process, and can_fast_process. A class that
370
370
caught_exception = start_successful = None
372
372
def call_end_proc(self):
373
"""Runs the end_process on self, checking for errors"""
373
u"""Runs the end_process on self, checking for errors"""
374
374
if self.finished or not self.start_successful:
375
375
self.caught_exception = 1
381
381
self.finished = 1
383
383
def start_process(self, *args):
384
"""Do some initial processing (stub)"""
384
u"""Do some initial processing (stub)"""
387
387
def end_process(self):
388
"""Do any final processing before leaving branch (stub)"""
388
u"""Do any final processing before leaving branch (stub)"""
391
391
def branch_process(self, branch):
392
"""Process a branch right after it is finished (stub)"""
392
u"""Process a branch right after it is finished (stub)"""
393
393
assert branch.finished
396
396
def can_fast_process(self, *args):
397
"""True if object can be processed without new branch (stub)"""
397
u"""True if object can be processed without new branch (stub)"""
400
400
def fast_process(self, *args):
401
"""Process args without new child branch (stub)"""
401
u"""Process args without new child branch (stub)"""
404
404
def on_error(self, exc, *args):
405
"""This is run on any exception in start/end-process"""
405
u"""This is run on any exception in start/end-process"""
406
406
self.caught_exception = 1
407
407
if args and args[0] and isinstance(args[0], tuple):
408
408
filename = os.path.join(*args[0])
410
410
filename = os.path.join(*self.index) # pylint: disable=not-an-iterable
413
log.Warn(_("Error '%s' processing %s") % (exc, util.fsdecode(filename)),
413
log.Warn(_(u"Error '%s' processing %s") % (exc, util.fsdecode(filename)),
414
414
log.WarningCode.cannot_process,
415
415
util.escape(filename))
417
417
def log_prev_error(self, index):
418
"""Call function if no pending exception"""
418
u"""Call function if no pending exception"""
422
422
index_str = os.path.join(*index)
423
log.Warn(_("Skipping %s because of previous error") % util.fsdecode(index_str),
423
log.Warn(_(u"Skipping %s because of previous error") % util.fsdecode(index_str),
424
424
log.WarningCode.process_skipped,
425
425
util.escape(index_str))