diff --git a/neo4j/io/__init__.py b/neo4j/io/__init__.py index 862895d7f..7716e0189 100644 --- a/neo4j/io/__init__.py +++ b/neo4j/io/__init__.py @@ -43,6 +43,7 @@ import logging from logging import getLogger from random import choice +import socket from threading import ( Condition, RLock, @@ -52,6 +53,7 @@ from neo4j._exceptions import ( BoltError, BoltHandshakeError, + SocketDeadlineExceeded, ) from neo4j._deadline import ( connection_deadline, @@ -509,11 +511,12 @@ def _append(self, signature, fields=(), response=None): self.responses.append(response) def _send_all(self): - data = self.outbox.view() - if data: + with self.outbox.view() as data: + if not data: + return try: self.socket.sendall(data) - except OSError as error: + except (OSError, socket.timeout, SocketDeadlineExceeded) as error: self._set_defunct_write(error) self.outbox.clear() diff --git a/neo4j/io/_common.py b/neo4j/io/_common.py index a3f079108..f11ddd8e0 100644 --- a/neo4j/io/_common.py +++ b/neo4j/io/_common.py @@ -114,22 +114,21 @@ def _chunk_data(self): ) num_chunks = num_full_chunks + bool(chunk_rest) - data_view = memoryview(self._raw_data) - header_start = len(self._chunked_data) - data_start = header_start + 2 - raw_data_start = 0 - for i in range(num_chunks): - chunk_size = min(data_len - raw_data_start, - self._max_chunk_size) - self._chunked_data[header_start:data_start] = struct_pack( - ">H", chunk_size - ) - self._chunked_data[data_start:(data_start + chunk_size)] = \ - data_view[raw_data_start:(raw_data_start + chunk_size)] - header_start += chunk_size + 2 + with memoryview(self._raw_data) as data_view: + header_start = len(self._chunked_data) data_start = header_start + 2 - raw_data_start += chunk_size - del data_view + raw_data_start = 0 + for i in range(num_chunks): + chunk_size = min(data_len - raw_data_start, + self._max_chunk_size) + self._chunked_data[header_start:data_start] = struct_pack( + ">H", chunk_size + ) + self._chunked_data[data_start:(data_start + chunk_size)] = \ + data_view[raw_data_start:(raw_data_start + chunk_size)] + header_start += chunk_size + 2 + data_start = header_start + 2 + raw_data_start += chunk_size self._raw_data.clear() def wrap_message(self): diff --git a/neo4j/packstream.py b/neo4j/packstream.py index 406d761e4..ca82cf91f 100644 --- a/neo4j/packstream.py +++ b/neo4j/packstream.py @@ -477,9 +477,9 @@ def receive(self, sock, n_bytes): end = self.used + n_bytes if end > len(self.data): self.data += bytearray(end - len(self.data)) - view = memoryview(self.data) - while self.used < end: - n = sock.recv_into(view[self.used:end], end - self.used) - if n == 0: - raise OSError("No data") - self.used += n + with memoryview(self.data) as view: + while self.used < end: + n = sock.recv_into(view[self.used:end], end - self.used) + if n == 0: + raise OSError("No data") + self.used += n