Skip to content

Commit 8490f5a

Browse files
Issue python#23001: Few functions in modules mmap, ossaudiodev, socket, ssl, and
codecs, that accepted only read-only bytes-like object now accept writable bytes-like object too.
1 parent 0eac130 commit 8490f5a

14 files changed

Lines changed: 193 additions & 101 deletions

File tree

Doc/library/mmap.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,9 @@ To map anonymous memory, -1 should be passed as the fileno along with the length
174174
Optional arguments *start* and *end* are interpreted as in slice notation.
175175
Returns ``-1`` on failure.
176176

177+
.. versionchanged: 3.5
178+
Writable :term:`bytes-like object` is now accepted.
179+
177180
178181
.. method:: flush([offset[, size]])
179182

@@ -234,6 +237,9 @@ To map anonymous memory, -1 should be passed as the fileno along with the length
234237
Optional arguments *start* and *end* are interpreted as in slice notation.
235238
Returns ``-1`` on failure.
236239

240+
.. versionchanged: 3.5
241+
Writable :term:`bytes-like object` is now accepted.
242+
237243
238244
.. method:: seek(pos[, whence])
239245

@@ -261,6 +267,9 @@ To map anonymous memory, -1 should be passed as the fileno along with the length
261267
were written. If the mmap was created with :const:`ACCESS_READ`, then
262268
writing to it will raise a :exc:`TypeError` exception.
263269

270+
.. versionchanged: 3.5
271+
Writable :term:`bytes-like object` is now accepted.
272+
264273
265274
.. method:: write_byte(byte)
266275

Doc/library/ossaudiodev.rst

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -148,21 +148,30 @@ and (read-only) attributes:
148148

149149
.. method:: oss_audio_device.write(data)
150150

151-
Write the Python string *data* to the audio device and return the number of
152-
bytes written. If the audio device is in blocking mode (the default), the
153-
entire string is always written (again, this is different from usual Unix device
154-
semantics). If the device is in non-blocking mode, some data may not be written
151+
Write a :term:`bytes-like object` *data* to the audio device and return the
152+
number of bytes written. If the audio device is in blocking mode (the
153+
default), the entire data is always written (again, this is different from
154+
usual Unix device semantics). If the device is in non-blocking mode, some
155+
data may not be written
155156
---see :meth:`writeall`.
156157

158+
.. versionchanged: 3.5
159+
Writable :term:`bytes-like object` is now accepted.
160+
157161
158162
.. method:: oss_audio_device.writeall(data)
159163

160-
Write the entire Python string *data* to the audio device: waits until the audio
161-
device is able to accept data, writes as much data as it will accept, and
162-
repeats until *data* has been completely written. If the device is in blocking
163-
mode (the default), this has the same effect as :meth:`write`; :meth:`writeall`
164-
is only useful in non-blocking mode. Has no return value, since the amount of
165-
data written is always equal to the amount of data supplied.
164+
Write a :term:`bytes-like object` *data* to the audio device: waits until
165+
the audio device is able to accept data, writes as much data as it will
166+
accept, and repeats until *data* has been completely written. If the device
167+
is in blocking mode (the default), this has the same effect as
168+
:meth:`write`; :meth:`writeall` is only useful in non-blocking mode. Has
169+
no return value, since the amount of data written is always equal to the
170+
amount of data supplied.
171+
172+
.. versionchanged: 3.5
173+
Writable :term:`bytes-like object` is now accepted.
174+
166175
167176
.. versionchanged:: 3.2
168177
Audio device objects also support the context management protocol, i.e. they can

Doc/library/socket.rst

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,20 @@ created. Socket addresses are represented as follows:
4646
- The address of an :const:`AF_UNIX` socket bound to a file system node
4747
is represented as a string, using the file system encoding and the
4848
``'surrogateescape'`` error handler (see :pep:`383`). An address in
49-
Linux's abstract namespace is returned as a :class:`bytes` object with
49+
Linux's abstract namespace is returned as a :term:`bytes-like object` with
5050
an initial null byte; note that sockets in this namespace can
5151
communicate with normal file system sockets, so programs intended to
5252
run on Linux may need to deal with both types of address. A string or
53-
:class:`bytes` object can be used for either type of address when
53+
bytes-like object can be used for either type of address when
5454
passing it as an argument.
5555

5656
.. versionchanged:: 3.3
5757
Previously, :const:`AF_UNIX` socket paths were assumed to use UTF-8
5858
encoding.
5959

60+
.. versionchanged: 3.5
61+
Writable :term:`bytes-like object` is now accepted.
62+
6063
- A pair ``(host, port)`` is used for the :const:`AF_INET` address family,
6164
where *host* is a string representing either a hostname in Internet domain
6265
notation like ``'daring.cwi.nl'`` or an IPv4 address like ``'100.50.200.5'``,
@@ -609,8 +612,8 @@ The :mod:`socket` module also offers various network-related services:
609612

610613
.. function:: inet_ntoa(packed_ip)
611614

612-
Convert a 32-bit packed IPv4 address (a bytes object four characters in
613-
length) to its standard dotted-quad string representation (for example,
615+
Convert a 32-bit packed IPv4 address (a :term:`bytes-like object` four
616+
bytes in length) to its standard dotted-quad string representation (for example,
614617
'123.45.67.89'). This is useful when conversing with a program that uses the
615618
standard C library and needs objects of type :c:type:`struct in_addr`, which
616619
is the C type for the 32-bit packed binary data this function takes as an
@@ -621,6 +624,9 @@ The :mod:`socket` module also offers various network-related services:
621624
support IPv6, and :func:`inet_ntop` should be used instead for IPv4/v6 dual
622625
stack support.
623626

627+
.. versionchanged: 3.5
628+
Writable :term:`bytes-like object` is now accepted.
629+
624630
625631
.. function:: inet_pton(address_family, ip_string)
626632

@@ -643,22 +649,26 @@ The :mod:`socket` module also offers various network-related services:
643649

644650
.. function:: inet_ntop(address_family, packed_ip)
645651

646-
Convert a packed IP address (a bytes object of some number of characters) to its
647-
standard, family-specific string representation (for example, ``'7.10.0.5'`` or
648-
``'5aef:2b::8'``). :func:`inet_ntop` is useful when a library or network protocol
649-
returns an object of type :c:type:`struct in_addr` (similar to :func:`inet_ntoa`)
650-
or :c:type:`struct in6_addr`.
652+
Convert a packed IP address (a :term:`bytes-like object` of some number of
653+
bytes) to its standard, family-specific string representation (for
654+
example, ``'7.10.0.5'`` or ``'5aef:2b::8'``).
655+
:func:`inet_ntop` is useful when a library or network protocol returns an
656+
object of type :c:type:`struct in_addr` (similar to :func:`inet_ntoa`) or
657+
:c:type:`struct in6_addr`.
651658

652659
Supported values for *address_family* are currently :const:`AF_INET` and
653-
:const:`AF_INET6`. If the string *packed_ip* is not the correct length for the
654-
specified address family, :exc:`ValueError` will be raised. A
655-
:exc:`OSError` is raised for errors from the call to :func:`inet_ntop`.
660+
:const:`AF_INET6`. If the bytes object *packed_ip* is not the correct
661+
length for the specified address family, :exc:`ValueError` will be raised.
662+
A :exc:`OSError` is raised for errors from the call to :func:`inet_ntop`.
656663

657664
Availability: Unix (maybe not all platforms), Windows.
658665

659666
.. versionchanged:: 3.4
660667
Windows support added
661668

669+
.. versionchanged: 3.5
670+
Writable :term:`bytes-like object` is now accepted.
671+
662672
663673
..
664674
XXX: Are sendmsg(), recvmsg() and CMSG_*() available on any
@@ -1207,11 +1217,15 @@ to sockets.
12071217

12081218
Set the value of the given socket option (see the Unix manual page
12091219
:manpage:`setsockopt(2)`). The needed symbolic constants are defined in the
1210-
:mod:`socket` module (:const:`SO_\*` etc.). The value can be an integer or a
1211-
bytes object representing a buffer. In the latter case it is up to the caller to
1220+
:mod:`socket` module (:const:`SO_\*` etc.). The value can be an integer or
1221+
a :term:`bytes-like object` representing a buffer. In the latter case it is
1222+
up to the caller to
12121223
ensure that the bytestring contains the proper bits (see the optional built-in
12131224
module :mod:`struct` for a way to encode C structures as bytestrings).
12141225

1226+
.. versionchanged: 3.5
1227+
Writable :term:`bytes-like object` is now accepted.
1228+
12151229
12161230
.. method:: socket.shutdown(how)
12171231

Doc/library/ssl.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,9 @@ Random generation
340340
string (so you can always use :const:`0.0`). See :rfc:`1750` for more
341341
information on sources of entropy.
342342

343+
.. versionchanged: 3.5
344+
Writable :term:`bytes-like object` is now accepted.
345+
343346
Certificate handling
344347
^^^^^^^^^^^^^^^^^^^^
345348

Lib/test/test_codecs.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,6 +1086,7 @@ def test_stream_bare(self):
10861086
class EscapeDecodeTest(unittest.TestCase):
10871087
def test_empty(self):
10881088
self.assertEqual(codecs.escape_decode(b""), (b"", 0))
1089+
self.assertEqual(codecs.escape_decode(bytearray()), (b"", 0))
10891090

10901091
def test_raw(self):
10911092
decode = codecs.escape_decode

Lib/test/test_mmap.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ def test_find_end(self):
282282
self.assertEqual(m.find(b'one', 1), 8)
283283
self.assertEqual(m.find(b'one', 1, -1), 8)
284284
self.assertEqual(m.find(b'one', 1, -2), -1)
285+
self.assertEqual(m.find(bytearray(b'one')), 0)
285286

286287

287288
def test_rfind(self):
@@ -300,6 +301,7 @@ def test_rfind(self):
300301
self.assertEqual(m.rfind(b'one', 0, -2), 0)
301302
self.assertEqual(m.rfind(b'one', 1, -1), 8)
302303
self.assertEqual(m.rfind(b'one', 1, -2), -1)
304+
self.assertEqual(m.rfind(bytearray(b'one')), 8)
303305

304306

305307
def test_double_close(self):
@@ -601,8 +603,10 @@ def test_io_methods(self):
601603
m.write(b"bar")
602604
self.assertEqual(m.tell(), 6)
603605
self.assertEqual(m[:], b"012bar6789")
604-
m.seek(8)
605-
self.assertRaises(ValueError, m.write, b"bar")
606+
m.write(bytearray(b"baz"))
607+
self.assertEqual(m.tell(), 9)
608+
self.assertEqual(m[:], b"012barbaz9")
609+
self.assertRaises(ValueError, m.write, b"ba")
606610

607611
def test_non_ascii_byte(self):
608612
for b in (129, 200, 255): # > 128

Lib/test/test_socket.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,13 +1074,15 @@ def testStringToIPv4(self):
10741074
assertInvalid(f, b'\x00' * 3)
10751075
assertInvalid(f, b'\x00' * 5)
10761076
assertInvalid(f, b'\x00' * 16)
1077+
self.assertEqual('170.85.170.85', f(bytearray(b'\xaa\x55\xaa\x55')))
10771078

10781079
self.assertEqual('1.0.1.0', g(b'\x01\x00\x01\x00'))
10791080
self.assertEqual('170.85.170.85', g(b'\xaa\x55\xaa\x55'))
10801081
self.assertEqual('255.255.255.255', g(b'\xff\xff\xff\xff'))
10811082
assertInvalid(g, b'\x00' * 3)
10821083
assertInvalid(g, b'\x00' * 5)
10831084
assertInvalid(g, b'\x00' * 16)
1085+
self.assertEqual('170.85.170.85', g(bytearray(b'\xaa\x55\xaa\x55')))
10841086

10851087
@unittest.skipUnless(hasattr(socket, 'inet_ntop'),
10861088
'test needs socket.inet_ntop()')
@@ -1110,6 +1112,7 @@ def testStringToIPv6(self):
11101112
'aef:b01:506:1001:ffff:9997:55:170',
11111113
f(b'\x0a\xef\x0b\x01\x05\x06\x10\x01\xff\xff\x99\x97\x00\x55\x01\x70')
11121114
)
1115+
self.assertEqual('::1', f(bytearray(b'\x00' * 15 + b'\x01')))
11131116

11141117
assertInvalid(b'\x12' * 15)
11151118
assertInvalid(b'\x12' * 17)
@@ -1497,6 +1500,7 @@ def testFilter(self):
14971500
s.setsockopt(socket.SOL_CAN_RAW, socket.CAN_RAW_FILTER, can_filter)
14981501
self.assertEqual(can_filter,
14991502
s.getsockopt(socket.SOL_CAN_RAW, socket.CAN_RAW_FILTER, 8))
1503+
s.setsockopt(socket.SOL_CAN_RAW, socket.CAN_RAW_FILTER, bytearray(can_filter))
15001504

15011505

15021506
@unittest.skipUnless(HAVE_SOCKET_CAN, 'SocketCan required for this test.')
@@ -4508,6 +4512,12 @@ def testStrName(self):
45084512
finally:
45094513
s.close()
45104514

4515+
def testBytearrayName(self):
4516+
# Check that an abstract name can be passed as a bytearray.
4517+
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s:
4518+
s.bind(bytearray(b"\x00python\x00test\x00"))
4519+
self.assertEqual(s.getsockname(), b"\x00python\x00test\x00")
4520+
45114521
@unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'test needs socket.AF_UNIX')
45124522
class TestUnixDomain(unittest.TestCase):
45134523

Lib/test/test_ssl.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,8 @@ def test_random(self):
171171
self.assertRaises(TypeError, ssl.RAND_egd, 1)
172172
self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1)
173173
ssl.RAND_add("this is a random string", 75.0)
174+
ssl.RAND_add(b"this is a random bytes object", 75.0)
175+
ssl.RAND_add(bytearray(b"this is a random bytearray object"), 75.0)
174176

175177
@unittest.skipUnless(os.name == 'posix', 'requires posix')
176178
def test_random_fork(self):

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ Core and Builtins
2121
Library
2222
-------
2323

24+
- Issue #23001: Few functions in modules mmap, ossaudiodev, socket, ssl, and
25+
codecs, that accepted only read-only bytes-like object now accept writable
26+
bytes-like object too.
27+
2428
- Issue #23646: If time.sleep() is interrupted by a signal, the sleep is now
2529
retried with the recomputed delay, except if the signal handler raises an
2630
exception (PEP 475).

Modules/_codecsmodule.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -208,15 +208,18 @@ static PyObject *
208208
escape_decode(PyObject *self,
209209
PyObject *args)
210210
{
211+
Py_buffer pbuf;
211212
const char *errors = NULL;
212-
const char *data;
213-
Py_ssize_t size;
213+
PyObject *result;
214214

215-
if (!PyArg_ParseTuple(args, "s#|z:escape_decode",
216-
&data, &size, &errors))
215+
if (!PyArg_ParseTuple(args, "s*|z:escape_decode",
216+
&pbuf, &errors))
217217
return NULL;
218-
return codec_tuple(PyBytes_DecodeEscape(data, size, errors, 0, NULL),
219-
size);
218+
result = codec_tuple(
219+
PyBytes_DecodeEscape(pbuf.buf, pbuf.len, errors, 0, NULL),
220+
pbuf.len);
221+
PyBuffer_Release(&pbuf);
222+
return result;
220223
}
221224

222225
static PyObject *

0 commit comments

Comments
 (0)