#!/usr/bin/env python3 'stream.py - by Sean B. Palmer' import sys, os, itertools, shutil def exit(*args): for arg in args: if isinstance(arg, int): sys.exit(arg) elif hasattr(arg, '__call__'): arg() else: print(arg) sys.exit() class Stream(object): def __init__(self, filename): self.oldfn = filename + '.old' self.newfn = filename if os.path.exists(self.oldfn): exit('File exists: %s' % self.oldfn, 1) shutil.copy(self.newfn, self.oldfn) self.old = open(self.oldfn, encoding='utf=8') self.new = open(self.newfn, 'w', encoding='utf-8') self.previous = None self.next = None self.collection = None self.closed = False def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): while True: if not self.move(): break self.append(self.previous) self.close() os.remove(self.oldfn) def move(self): try: line = self.old.__next__() except StopIteration: line = None except ValueError: line = None self.previous = self.next self.next = line return (self.previous is not None) or (self.next is not None) def append(self, line): if line is None: return if not self.new.closed: self.new.write(line) if self.collection is not None: self.collection.append(line) def collect(self): self.collection = [] def collected(self): collection = self.collection self.collection = None return collection def edit(self, ordinal, string, test, skip=False): found = 0 want = int(ordinal[:-2]) while True: line = getattr(self, test) if line and (string in line): found += 1 if found >= want: if skip: self.move() return True if not self.move(): break self.append(self.previous) return False def before(self, ordinal, string): return self.edit(ordinal, string, 'next') def instead(self, ordinal, string): return self.edit(ordinal, string, 'next', skip=True) def after(self, ordinal, string): return self.edit(ordinal, string, 'previous') def write(self, text): self.append(text + '\n') def close(self): self.old.close() self.new.close() self.closed = True if __name__ == '__main__': print(__doc__)