Issue2062

classification
Title: bytearray not accepted for os.write
Type: behaviour Severity: normal
Components: Core Versions: Jython 2.7
Milestone:
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: jeff.allen Nosy List: jamesls, jeff.allen, santa4nt, zyasoft
Priority: Keywords: patch

Created on 2013-06-18.04:04:14 by jamesls, last changed 2014-06-24.20:02:43 by jeff.allen.

Files
File name Uploaded Description Edit Remove
os_write_bytearray.diff santa4nt, 2013-06-18.21:42:04 Adding an overloaded write() method that takes bytearray.
Messages
msg8048 (view) Author: James (jamesls) Date: 2013-06-18.04:04:13
Using the latest jython2.7, I'm not able to use bytearray with os.write.
In CPython2.7.5 I get:

>>> import os
>>> fd = os.open('/tmp/foo', os.O_RDWR)
>>> os.write(fd, bytearray('foobar'))
6

From jython 2.7b1 I get:

>>> import os
>>> fd = os.open('/tmp/foo', os.O_RDWR)
>>> os.write(fd, bytearray('foobar'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: write(): 2nd arg can't be coerced to String
msg8049 (view) Author: Santoso Wijaya (santa4nt) Date: 2013-06-18.21:42:04
A quick-n-dirty fix with adding an overloaded method.
msg8198 (view) Author: Jeff Allen (jeff.allen) Date: 2013-12-14.22:40:17
A complete solution, here and many other places where a String argument really means bytes, is to accept any PyObject supporting the Buffer API. Then this would work as it does on CPython:

>>> fd = os.open('x.tmp', os.O_CREAT | os.O_RDWR)
>>> a = bytearray("Stuff and nonsense. ")
>>> os.write(fd, a)
20
>>> os.write(fd, buffer(a))
20
>>> os.write(fd, memoryview(a))
20

It would be cool to find some automagic implementation, but I think it has to be a ByteUtil class (or some such), offering few well-crafted static methods, and a re-write of these methods one by one. Asking a buffer for its String is least work but goes completely against the idea of the buffer API as efficient in-place access, unless it's really a PyString after all.
msg8476 (view) Author: Jim Baker (zyasoft) Date: 2014-05-21.21:22:41
Blocker for beta 4
msg8649 (view) Author: Jeff Allen (jeff.allen) Date: 2014-06-15.23:37:19
Clean & polished fix, now in my local code base, behaves like this:
>>> import os
>>> s = "This is a test."
>>> m = memoryview(s)
>>> fd = os.open("x.tmp", os.O_WRONLY | os.O_CREAT)
>>> os.write(fd, s)
15
>>> os.write(fd, m)
15
>>> os.write(fd, bytearray(s))
15
>>> os.write(fd, buffer(s))
15
>>> os.write(fd, 1.5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: write(): 2nd arg can't be coerced to org.python.core.BufferProtocol
>>> os.write(fd, m[1::2])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
BufferError: underlying buffer is not C-contiguous
>>> os.close(fd)
>>> os.write(fd, s)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 9] Bad file descriptor 

I was surprised that I could declare this simply as:
public static int write(PyObject fd, BufferProtocol bytes)
and let Jython take care of the type test. (Indra Talip did this in binascii.) Previously I've accepted a PyObject, then tested it with instanceof. It means the error message is not quite the same as CPython when you hand it, say, a float in place of bytes, but the code is simpler.
msg8662 (view) Author: Jeff Allen (jeff.allen) Date: 2014-06-18.07:25:39
Hmm ... a test: good idea. I'll add one to test_os_jy.
msg8816 (view) Author: Jim Baker (zyasoft) Date: 2014-06-24.18:33:15
I assume we are still pending a test, but otherwise it is certainly fixed. I will keep this open for another week or so.
msg8817 (view) Author: Jeff Allen (jeff.allen) Date: 2014-06-24.20:02:43
The test is here http://hg.python.org/jython/rev/0944779f5d1c, so I take your "unless" as a vote to close, and agree.
History
Date User Action Args
2014-06-24 20:02:43jeff.allensetstatus: pending -> closed
messages: + msg8817
2014-06-24 18:33:15zyasoftsetmessages: + msg8816
2014-06-18 07:25:39jeff.allensetmessages: + msg8662
2014-06-15 23:37:19jeff.allensetstatus: open -> pending
resolution: accepted -> fixed
messages: + msg8649
2014-06-15 15:49:51jeff.allensetassignee: jeff.allen
2014-05-21 21:22:41zyasoftsetresolution: accepted
messages: + msg8476
nosy: + zyasoft
2013-12-14 22:40:17jeff.allensetnosy: + jeff.allen
messages: + msg8198
2013-06-18 21:42:04santa4ntsetfiles: + os_write_bytearray.diff
keywords: + patch
messages: + msg8049
nosy: + santa4nt
2013-06-18 04:04:14jameslscreate