Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

read() must be called from an active context manager #34

Closed
zeromake opened this issue Dec 1, 2017 · 2 comments
Closed

read() must be called from an active context manager #34

zeromake opened this issue Dec 1, 2017 · 2 comments

Comments

@zeromake
Copy link

zeromake commented Dec 1, 2017

ENV

  1. system: linux
  2. python: 3.6.3
  3. zstandard: 0.9.0.dev0

simulation to io.RawIOBase

test.py

import io
import zstandard as zstd
class ZstdDecompressReader(io.RawIOBase):
    def __init__(self, fp):
        self._fp = fp
        self._eof = False
        self._pos = 0
        self._size = -1
        self._decompressor = zstd.ZstdDecompressor()
        self._stream_reader = None
    def close(self):
        self._decompressor = None
        if self._stream_reader:
            self._stream_reader.close()
            self._stream_reader = None
        return super().close()

    def read(self, size=-1):
        if size < 0:
            return self.readall()
        if not size or self._eof:
            return b""
        if not self._stream_reader:
            self._stream_reader = self._decompressor.stream_reader(self._fp)
        data = self._stream_reader.read(size)
        if not data:
            self._eof = True
            self._size = self._pos
            return b""
        self._pos += len(data)
        return data

if __name__ == '__main__':
    with open('1.tar.zstd', 'rb') as fp:
        decompress = ZstdDecompressReader(fp)
        print(decompress.read(10))

python test.py

Traceback (most recent call last):
  File "./test.py", line 36, in <module>
    print(decompress.read(10))
  File "./test.py", line 25, in read
    data = self._stream_reader.read(size)
zstd.ZstdError: read() must be called from an active context manager

can run

import io
import zstandard as zstd
class ZstdDecompressReader(io.RawIOBase):
    def __init__(self, fp):
        self._fp = fp
        self._eof = False
        self._pos = 0
        self._size = -1
        self._decompressor = zstd.ZstdDecompressor()
        self._stream_reader = None
    def close(self):
        self._decompressor = None
        if self._stream_reader:
            self._stream_reader.__exit__()
            # self._stream_reader.close()
            self._stream_reader = None
        return super().close()

    def read(self, size=-1):
        if size < 0:
            return self.readall()
        if not size or self._eof:
            return b""
        if not self._stream_reader:
            self._stream_reader = self._decompressor.stream_reader(self._fp)
            self._stream_reader.__enter__()
        data = self._stream_reader.read(size)
        if not data:
            self._eof = True
            self._size = self._pos
            return b""
        self._pos += len(data)
        return data

if __name__ == '__main__':
    with open('1.tar.zstd', 'rb') as fp:
        decompressor = zstd.ZstdDecompressor()
        decompress = ZstdDecompressReader(fp)
        print(decompress.read(10))

or

import io
import zstandard as zstd
class ZstdDecompressReader(io.RawIOBase):
    def __init__(self, decompressor, stream_reader):
        self._fp = fp
        self._eof = False
        self._pos = 0
        self._size = -1
        self._decompressor = decompressor
        self._stream_reader = stream_reader
    def close(self):
        self._decompressor = None
        if self._stream_reader:
            self._stream_reader.close()
            self._stream_reader = None
        return super().close()

    def read(self, size=-1):
        if size < 0:
            return self.readall()
        if not size or self._eof:
            return b""
        if not self._stream_reader:
            self._stream_reader = self._decompressor.stream_reader(self._fp)
        data = self._stream_reader.read(size)
        if not data:
            self._eof = True
            self._size = self._pos
            return b""
        self._pos += len(data)
        return data

if __name__ == '__main__':
    with open('1.tar.zstd', 'rb') as fp:
        decompressor = zstd.ZstdDecompressor()
        with decompressor.stream_reader(fp) as stream_reader:
            decompress = ZstdDecompressReader(decompressor, stream_reader)
            print(decompress.read(10))
            print(decompress.read(10))

suggest

So should it be not context manager

@indygreg
Copy link
Owner

indygreg commented Jun 5, 2018

Thinking about this some more, I agree that the stream_reader() and stream_writer() interfaces should not require a context manager. I'll try to work this into the next release.

@indygreg
Copy link
Owner

indygreg commented Oct 7, 2018

The next release won't require stream_reader() to be used as a context manager.

stream_writer() is a bit harder to change. I may or may not do that in the next release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants