def test_different_format_writes(self): LAYOUT = "int8_2" loop = asyncio.get_event_loop() my_pipe = LocalPipe(LAYOUT, name="testpipe") test_data = helpers.create_data(LAYOUT, length=4, step=1, start=106) async def write(): # write unstructured numpy arrays await my_pipe.write(np.array([[1, 1, 1]])) await my_pipe.write(np.array([[2, 2, 2], [3, 3, 3]])) # logs empty writes with self.assertLogs(level="INFO") as logs: await my_pipe.write(np.array([[]])) # errors on invalid write types bad_data = [[100, 1, 2], 'invalid', 4, None, np.array([4, 8])] for data in bad_data: with self.assertRaises(PipeError): await my_pipe.write(data) # write structured numpy arrays await my_pipe.write(test_data) loop = asyncio.get_event_loop() loop.run_until_complete(write()) result = my_pipe.read_nowait(flatten=True) np.testing.assert_array_equal(result[:3], [[1, 1, 1], [2, 2, 2], [3, 3, 3]]) my_pipe.consume(3) result = my_pipe.read_nowait() np.testing.assert_array_equal(result, test_data)
def test_nowait_read_does_not_block(self): LAYOUT = "int8_2" LENGTH = 50 my_pipe = LocalPipe(LAYOUT) test_data = helpers.create_data(LAYOUT, length=LENGTH) my_pipe.write_nowait(test_data) self.assertEqual(len(my_pipe.read_nowait()), LENGTH) # another read executes immediately because there is unconsumed data self.assertEqual(len(my_pipe.read_nowait()), LENGTH) # now consume the data and the next call to read execute immediately # even though there is no data to be returned my_pipe.consume(LENGTH) self.assertEqual(0, len(my_pipe.read_nowait(flatten=True))) return
def test_raises_consume_errors(self): LAYOUT = "int32_3" LENGTH = 1000 my_pipe = LocalPipe(LAYOUT) test_data = helpers.create_data(LAYOUT, length=LENGTH) my_pipe.write_nowait(test_data) read_data = my_pipe.read_nowait() # can't consume more than was read with self.assertRaises(PipeError) as e: my_pipe.consume(len(read_data) + 1) self.assertTrue('consume' in str(e.exception)) # can't consume less than zero with self.assertRaises(PipeError) as e: my_pipe.consume(-1) self.assertTrue('negative' in str(e.exception))
class TestingPipe(Pipe): # reads come out in the same blocks as the writes # ...wraps LocalPipe def __init__(self, layout: str, name: str = None, stream=None): super().__init__(name=name, layout=layout, stream=stream) self._pipe = LocalPipe(layout, name, stream) self._closed = False self.data_blocks: deque = deque() async def write(self, data): if self._closed: raise PipeError("Cannot write to a closed pipe") self.data_blocks.append(data) def write_nowait(self, data): if self._closed: raise PipeError("Cannot write to a closed pipe") self.data_blocks.append(data) def close_interval_no_wait(self): self.data_blocks.append(None) async def close_interval(self): self.data_blocks.append(None) def consume(self, rows): return self._pipe.consume(rows) def reread_last(self): self._pipe.reread_last() @property def end_of_interval(self): return self._pipe.end_of_interval async def read(self, flatten=False): # first write a block to the pipe if there are any waiting if len(self.data_blocks) > 0: block = self.data_blocks.popleft() if block is None: await self._pipe.close_interval() else: await self._pipe.write(block) elif self._closed: await self._pipe.close() # now return the result of the inner pipe's read return await self._pipe.read(flatten) def is_empty(self): return self._pipe.is_empty() async def close(self): self._closed = True
async def _run(): LAYOUT = "float32_3" LENGTH = 100 pipe = LocalPipe(layout="float32_3") tx_data = helpers.create_data(LAYOUT, length=LENGTH) # write a block and close off the pipe await pipe.write(tx_data) await pipe.close() # read it back rx_data = await pipe.read() np.testing.assert_array_equal(tx_data, rx_data) # don't consume it so you can read it agai pipe.consume(len(rx_data[:500])) # read it back again rx_data = await pipe.read() np.testing.assert_array_equal(tx_data[500:], rx_data) # the pipe should be empty now self.assertTrue(pipe.is_empty()) with self.assertRaises(EmptyPipeError): await pipe.read()