diff --git a/msgpack/_unpacker.pyx b/msgpack/_unpacker.pyx index 3c81808f..44f83f09 100644 --- a/msgpack/_unpacker.pyx +++ b/msgpack/_unpacker.pyx @@ -360,7 +360,7 @@ cdef class Unpacker: self.ext_hook = ext_hook self.file_like = file_like - if file_like: + if file_like is not None: self.file_like_read = file_like.read if not PyCallable_Check(self.file_like_read): raise TypeError("`file_like.read` must be a callable.") diff --git a/test/test_sequnpack.py b/test/test_sequnpack.py index 904be42f..4588126b 100644 --- a/test/test_sequnpack.py +++ b/test/test_sequnpack.py @@ -87,6 +87,21 @@ def test_maxbuffersize_file(): print(unpacker.unpack()) +def test_falsy_file_like(): + # A file-like object may define __bool__ or __len__ and be falsy + # (e.g. a file wrapper without a name). Only `.read()` is required. + class FalsyBytesIO(io.BytesIO): + def __bool__(self): + return False + + stream = FalsyBytesIO(packb([1, 2]) + packb({"a": 3})) + assert list(Unpacker(stream)) == [[1, 2], {"a": 3}] + + unpacker = Unpacker(FalsyBytesIO(packb(1) + b"xy")) + assert unpacker.unpack() == 1 + assert unpacker.read_bytes(2) == b"xy" + + def test_readbytes(): unpacker = Unpacker(read_size=3) unpacker.feed(b"foobar")