Peekable Pushable Generators - Spicery/Nutmeg GitHub Wiki

Here's a class that you can use to wrap any iterator so that you can peek ahead, push values back onto the stream and check for empty. It's a simple idea with a simple implementation that I've found very handy in the past. (Copied and slightly improved from my old stackoverflow post).

class PeekablePushable:

    def __init__(self, iter):
        self.source = iter
        self.stored = []

    def __iter__(self):
        return self

    def __bool__(self):
        if self.stored:
            return True
        try:
            self.stored.append(next(self.source))
        except StopIteration:
            return False
        return True

    def push(self, value):
        self.stored.append(value)

    def peek(self):
        if self.stored:
            return self.stored[-1]
        value = next(self.source)
        self.stored.append(value)
        return value

    def peekOrElse(self, orElse=None):
        try:
            return self.peek()
        except StopIteration:
            return orElse

    def pop(self):
        """A synonym for __next__()"""
        return self.__next__()

    def __next__(self):
        if self.stored:
            return self.stored.pop()
        return next(self.source)