bitarray from buffer incorrectly labelled as readonly in PyPy
scott-griffiths opened this issue · 2 comments
Hi again!
Tested with PyPy 7.3.9 (Python 3.7.13) and bitarray 2.7.3
I only get this behaviour with PyPy
>>>> a = bitarray.bitarray(buffer=bytearray(10))
>>>> a.readonly
True
I would expect this to be False
as bytearrays are mutable, and it is false in CPython.
I looked through the source code to try to understand if this is a PyPy bug, and my best guess is that the flag used for getting the buffer (https://github.com/ilanschnell/bitarray/blob/550c5031f72750b6565fccbe20dce33e57a24ee1/bitarray/_bitarray.c#LL3273C16-L3273C16) is PyBUF_SIMPLE
and maybe should be PyBUF_WRITABLE
? Or possibly a bit more subtle than that to avoid writable buffers for immutable types!
The documentation (https://docs.python.org/3/c-api/buffer.html#readonly-format) says that if you don't use PyBUF_WRITABLE
then "the exporter MAY provide either a read-only or writable buffer, but the choice MUST be consistent for all consumers." So PyPy might just be choosing to give a read-only buffer even though it's a bytearray
object as it is allowed to do so, whereas CPython chooses a writable buffer.
I haven't tried a fix myself as it's a bit out of my comfort zone, but I might try dusting off a C compiler if I get a chance some time.
Thanks.
Thanks for reporting this issue! As you mentioned a.readonly
is False
when using cpython in your example, and
>>> a = bitarray.bitarray(buffer=b'asdfg') # import from immutable bytes object
>>> a.readonly
True
The Python documentation also says: PyBUF_WRITABLE Controls the readonly field. If set, the exporter MUST provide a writable buffer or else report failure.
I tried changing line 3273 to use PyBUF_WRITABLE
, but this gives me test failures. In particular with this change, I get:
>>> a = bitarray.bitarray(buffer=b'asdfg')
BufferError: Object is not writable.
This makes sense, as here the buffer is not writable.
I consider this problem a bug in PyPy. I'm not using PyPy myself, and bitarray doesn't have full PyPy support (which is also why no PyPy wheels are available on PyPi).
If this issue is important to you, I would let the PyPy community know about.
Thanks again
OK, no problem. I managed to work around it by creating an empty bitarray
and initialising it with .frombytes()
instead. Not quite equivalent, but close enough for me.
I'm not convinced it's a PyPy bug though - the docs suggest that the exporter in CPython could provide a read-only buffer if you use PyBUF_SIMPLE
as long as it did so consistently, so my reading of that is that the code could break in a future CPython version.
Thanks.