Breaks enumerable argument into batch size enumerable pieces. The last chunk can
    be of any length up to batch_size.

    batch(xrange(5), 3)
    # => [0, 1, 2], [3, 4]

def batch(enumerable, batch_size):
    '''
    Breaks enumerable argument into batch size enumerable pieces. The last chunk can
    be of any length up to batch_size.

    batch(xrange(5), 3)
    # => [0, 1, 2], [3, 4]
    '''
    batch_size = max(int(batch_size), 1)
    try:
        enumerable.__getitem__
        total_size = len(enumerable)
    except (TypeError, AttributeError):
        enumerable = list(enumerable)
        total_size = len(enumerable)
    if total_size == 0:
        yield tuple()
    try:
        for batch_index in xrange(0, total_size, batch_size):
            yield enumerable[batch_index:min(batch_index + batch_size, total_size)]
    except TypeError:
        # Fall back on islice, though it's not as efficient the way we're using it
        for batch_start in xrange(0, total_size, batch_size):
            yield tuple(islice(enumerable, batch_start, min(batch_start + batch_size, total_size)))