Repository navigation
Conversation
Unpacker.__init__ in the C extension used `if file_like:` before saving `file_like.read`. A stream that defines __bool__ or __len__ and is falsy (for example werkzeug's FileStorage without a filename) was stored as the input but its read method was not, so the first read failed with "TypeError: 'NoneType' object is not callable". The pure Python Unpacker checks `file_like is None` and works. Check `file_like is not None` instead and add a regression test.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Unpacker(file_like)in the C extension checksif file_like:before it looks upfile_like.read. A stream that defines__bool__or__len__and is falsy is therefore stored as the input source, but itsreadmethod is never saved. The firstunpack(),next()orread_bytes()that needs data then fails withTypeError: 'NoneType' object is not callable.Such objects are common file wrappers. For example, werkzeug's
FileStorageis falsy when it has no filename, soUnpacker(FileStorage(io.BytesIO(data), filename=""))fails with the C extension. The pure PythonUnpackerchecksfile_like is Noneand unpacks the same stream correctly, and the documentation only asks for an object with a.read(n)method.This PR changes the check to
if file_like is not None:, which matches the fallback and the rest of the class (feed(),read_bytes()and_unpack()already testself.file_like is not None).Nothing that worked before changes behaviour. A falsy non-
Nonefile_likecould not be used at all:feed()raisedAssertionErrorand reading raised theTypeErrorabove. A falsy object without areadattribute, such asb"", now raisesAttributeErrorin the constructor, as the fallback already does.A regression test in
test/test_sequnpack.pyunpacks two objects and callsread_bytes()on a falsyBytesIOsubclass. It fails with the C extension before this change and passes after it; it passes withMSGPACK_PUREPYTHON=1both before and after. The full test suite passes with the C extension (179 passed, 1 skipped) and with the pure Python implementation (176 passed, 4 skipped), andruff check/ruff format --checkare clean.This change was drafted with Claude Code (claude-opus-5-5); the test results above are from the runs described.