8000 gh-135862: fix asyncio socket partial writes of non-1d-binary arrays by duaneg · Pull Request #135974 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-135862: fix asyncio socket partial writes of non-1d-binary arrays #135974

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Lib/asyncio/selector_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -1077,7 +1077,11 @@ def write(self, data):
self._fatal_error(exc, 'Fatal write error on socket transport')
return
else:
data = memoryview(data)[n:]
if isinstance(data, memoryview):
data = data.cast('c')[n:]
else:
data = memoryview(data)[n:]
assert(data.itemsize == 1)
if not data:
return
# Not all was written; register write handler.
Expand Down
40 changes: 39 additions & 1 deletion Lib/test/test_asyncio/test_selector_events.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Tests for selector_events.py"""

import array
import collections
import selectors
import socket
Expand All @@ -13,6 +14,11 @@
except ImportError:
ssl = None

try:
from _testbuffer import *
except ImportError:
ndarray = None

import asyncio
from asyncio.selector_events import (BaseSelectorEventLoop,
_SelectorDatagramTransport,
Expand Down Expand Up @@ -768,7 +774,39 @@ def test_write_partial_memoryview(self):
transport.write(data)

self.loop.assert_writer(7, transport._write_ready)
self.assertEqual(list_to_buffer([b'ta']), transport._buffer)
self.assertEqualBufferContents(b'ta', transport._buffer)

def test_write_partial_nonbyte_array_memview_write(self):
arr = array.array('l', [-1, 1])
data = memoryview(arr)

self.sock.send.return_value = len(arr) * data.itemsize // 2

transport = self.socket_transport()
transport.write(data)

self.loop.assert_writer(7, transport._write_ready)
remainder = memoryview(array.array('l', [1]))
self.assertEqualBufferContents(remainder.tobytes(), transport._buffer)

@unittest.skipUnless(ndarray, 'ndarray object required for this test')
def test_write_partial_ndarray_memview_write(self):
items = (-2, -1, 1, 2)
arr = ndarray(items, format='l', shape=(1, 2, 2))
data = memoryview(arr)

self.sock.send.return_value = arr.nbytes // 2

transport = self.socket_transport()
transport.write(data)

self.loop.assert_writer(7, transport._write_ready)
remainder = memoryview(array.array('l', (1, 2)))
self.assertEqualBufferContents(remainder.tobytes(), transport._buffer)

def assertEqualBufferContents(self, expected, buffer):
self.assertEqual(len(buffer), 1)
self.assertEqual(expected, buffer[0].tobytes())

def test_write_partial_none(self):
data = b'data'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix bug where partial writes of :class:`memoryview` s of non-byte or 2+
dimensional arrays would write remaining binary data incorrectly.
Loading
0