async def test_sync_batch_context(self, table: Table): with pytest.raises(RuntimeError): with table.batch(): pass with pytest.raises(RuntimeError): table.batch().__enter__() batch = await table.batch().__aenter__() with pytest.raises(RuntimeError): batch.__exit__()
async def test_scan_reverse(self, table: Table): if table.connection.compat < '0.98': with pytest.raises(NotImplementedError): await self._scan_list(table, reverse=True) return async with table.batch() as b: for i in range(2000): await b.put(f'row-scan-reverse-{i:04}'.encode('ascii'), { b'cf1:col1': b'v1', b'cf1:col2': b'v2' }) scan = table.scan(row_prefix=b'row-scan-reverse', reverse=True) assert 2000 == await self._scan_len(scan) assert 10 == await self._tbl_scan_len(table, limit=10, reverse=True) scan = table.scan( row_start=b'row-scan-reverse-1999', row_stop=b'row-scan-reverse-0000', reverse=True, ) key, data = await scan.__anext__() assert b'row-scan-reverse-1999' == key key, data = [x async for x in scan][-1] assert b'row-scan-reverse-0001' == key
async def test_batch_order(self, table: Table): row = b'row-test-batch-order' col = b'cf1:col' async with table.batch() as b: for i in range(5): await b.put(row, {col: str(i).encode()}) assert (await table.row(row))[col] == b'4'
async def test_batch_delete_put_same_row(self, table: Table): # See https://github.com/python-happybase/happybase/issues/224 row = b'row-test-batch-delete-put' col = b'cf1:col' val = b'val' await table.put(row, {col: b''}) async with table.batch() as b: await b.delete(row) await b.put(row, {col: val}) result = await table.row(row) assert col in result assert result[col] == val
async def test_batch_counters(self, table: Table): row = b'row-with-counter' col1 = b'cf1:counter1' col2 = b'cf1:counter2' get = partial(table.counter_get, row) async def check_cols(c1: int, c2: int): for col, val in [(col1, c1), (col2, c2)]: assert await get(col) == val async with table.batch() as b: inc = partial(b.counter_inc, row) dec = partial(b.counter_dec, row) await inc(col1, 1) # c1 == 1, c2 == 0 await inc(col1, 2) # c1 == 3, c2 == 0 await dec(col2, 2) # c1 == 3, c2 == -2 await dec(col1, 1) # c1 == 2, c2 == -2 await inc(col2, 5) # c1 == 2, c2 == 3 # Make sure nothing was sent yet await check_cols(0, 0) await check_cols(2, 3) for c in [col1, col2]: await table.counter_set(row, c, 0) await check_cols(0, 0) async with table.batch(batch_size=2) as b: inc = partial(b.counter_inc, row) await inc(col1, 1) await check_cols(0, 0) # Not sent yet await inc(col1, 1) await check_cols(0, 0) # Same column modified twice, not sent await inc(col2, 1) # Forces send since batch count >= 2 await check_cols(2, 1)
async def test_batch_context_managers(self, table: Table): async with table.batch() as b: await b.put(b'row4', {b'cf1:col3': b'value3'}) await b.put(b'row5', {b'cf1:col4': b'value4'}) await b.put(b'row', {b'cf1:col1': b'value1'}) await b.delete(b'row', [b'cf1:col4']) await b.put(b'row', {b'cf1:col2': b'value2'}) async with table.batch(timestamp=87654321) as b: await b.put(b'row', { b'cf1:c3': b'somevalue', b'cf1:c5': b'anothervalue' }) await b.delete(b'row', [b'cf1:c3']) with pytest.raises(ValueError): async with table.batch(transaction=True) as b: await b.put(b'fooz', {b'cf1:bar': b'baz'}) raise ValueError assert {} == await table.row(b'fooz', [b'cf1:bar']) with pytest.raises(ValueError): async with table.batch(transaction=False) as b: await b.put(b'fooz', {b'cf1:bar': b'baz'}) raise ValueError assert {b'cf1:bar': b'baz'} == await table.row(b'fooz', [b'cf1:bar']) async with table.batch(batch_size=5) as b: for i in range(10): await b.put( f'row-batch1-{i:03}'.encode('ascii'), {b'cf1:': str(i).encode('ascii')}, ) async with table.batch(batch_size=20) as b: for i in range(95): await b.put( f'row-batch2-{i:03}'.encode('ascii'), {b'cf1:': str(i).encode('ascii')}, ) assert 95 == await self._tbl_scan_len(table, row_prefix=b'row-batch2-') async with table.batch(batch_size=20) as b: for i in range(95): await b.delete(f'row-batch2-{i:03}'.encode('ascii')) assert 0 == await self._tbl_scan_len(table, row_prefix=b'row-batch2-')
async def test_batch(self, table: Table): with pytest.raises(TypeError): table.batch(timestamp='invalid') # noqa b = table.batch() await b.put(b'row1', {b'cf1:col1': b'value1', b'cf1:col2': b'value2'}) await b.put(b'row2', { b'cf1:col1': b'value1', b'cf1:col2': b'value2', b'cf1:col3': b'value3' }) await b.delete(b'row1', [b'cf1:col4']) await b.delete(b'another-row') await b.close() table.batch(timestamp=1234567) await b.put(b'row1', {b'cf1:col5': b'value5'}) await b.close() with pytest.raises(ValueError): table.batch(batch_size=0) with pytest.raises(TypeError): table.batch(transaction=True, batch_size=10)
async def test_scan(self, table: Table): with pytest.raises(TypeError): await self._scan_list(table, row_prefix='foobar', row_start='xyz') if table.connection.compat == '0.90': with pytest.raises(NotImplementedError): await self._scan_list(table, filter='foo') if table.connection.compat < '0.96': with pytest.raises(NotImplementedError): await self._scan_list(table, sorted_columns=True) with pytest.raises(ValueError): await self._scan_list(table, batch_size=0) with pytest.raises(ValueError): await self._scan_list(table, limit=0) with pytest.raises(ValueError): await self._scan_list(table, scan_batching=0) async with table.batch() as b: for i in range(2000): await b.put( f'row-scan-a{i:05}'.encode('ascii'), { b'cf1:col1': b'v1', b'cf1:col2': b'v2', b'cf2:col1': b'v1', b'cf2:col2': b'v2' }) await b.put(f'row-scan-b{i:05}'.encode('ascii'), { b'cf1:col1': b'v1', b'cf1:col2': b'v2' }) scanner = table.scan( row_start=b'row-scan-a00012', row_stop=b'row-scan-a00022', ) assert 10 == await self._scan_len(scanner) scanner = table.scan(row_start=b'xyz') assert 0 == await self._scan_len(scanner) scanner = table.scan(row_start=b'xyz', row_stop=b'zyx') assert 0 == await self._scan_len(scanner) rows = await self._scan_list( table, row_start=b'row-scan-', row_stop=b'row-scan-a999', columns=[b'cf1:col1', b'cf2:col2'], ) row_key, row = rows[0] assert row_key == b'row-scan-a00000' assert row == {b'cf1:col1': b'v1', b'cf2:col2': b'v2'} assert 2000 == len(rows) scanner = table.scan( row_prefix=b'row-scan-a', batch_size=499, limit=1000, ) assert 1000 == await self._scan_len(scanner) scanner = table.scan( row_prefix=b'row-scan-b', batch_size=1, limit=10, ) assert 10 == await self._scan_len(scanner) scanner = table.scan( row_prefix=b'row-scan-b', batch_size=5, limit=10, ) assert 10 == await self._scan_len(scanner) scanner = table.scan(timestamp=123) assert 0 == await self._scan_len(scanner) scanner = table.scan(row_prefix=b'row', timestamp=123) assert 0 == await self._scan_len(scanner) scanner = table.scan(batch_size=20) await scanner.__anext__() await scanner.aclose() with pytest.raises(StopAsyncIteration): await scanner.__anext__()