def buffer_iterator(filelike, buffer_size=1048576, progress=None, max_bytes
    =None):
    """ Return an iterator of byte buffers

    The buffers of bytes default to the provided buffer_size.  This is a useful
    method when copying one data stream to another.

    Parameters
    ----------
    filelike : a file-like object
        An object which implements the :py:meth:`read(buffer_size)` method.
    buffer_size : int
        The number of bytes to read at a time.
    progress : callable
        A callback for progress indication.  A StoreProgressManager instance
        inside a ``with`` block would be appropriate, but anthing that takes a
        `step` parameter which is the total number of bytes read so far will
        work.
    max_bytes : int
        The maximum number of bytes to return.

    """
    progress = (progress if progress is not None else lambda *args, **
        kwargs: None)
    bytes_iterated = 0
    while max_bytes is None or bytes_iterated < max_bytes:
        chunk = filelike.read(buffer_size)
        if max_bytes is not None and max_bytes - bytes_iterated < len(chunk):
            chunk = chunk[:max_bytes - bytes_iterated]
        bytes_iterated += len(chunk)
        progress(step=bytes_iterated)
        if not chunk:
            break
        yield chunk
