From d455db0303067d3524c9b3c37ee1359231f0fe3b Mon Sep 17 00:00:00 2001 From: Kwangseob Kim Date: Thu, 30 Apr 2015 00:26:25 +0900 Subject: [PATCH 1/6] counter_incs by incrementRows --- happybase/table.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/happybase/table.py b/happybase/table.py index 3cb26b7..f35c49c 100644 --- a/happybase/table.py +++ b/happybase/table.py @@ -3,11 +3,12 @@ """ import logging +from itertools import izip from numbers import Integral from operator import attrgetter from struct import Struct -from .hbase.ttypes import TScan +from .hbase.ttypes import TScan, TIncrement from .util import thrift_type_to_dict, str_increment, OrderedDict from .batch import Batch @@ -558,6 +559,25 @@ def counter_inc(self, row, column, value=1): return self.connection.client.atomicIncrement( self.name, row, column, value) + def counter_incs(self, row, data): + """ + + This method increments of decrements the counter columns in the row + specified by `row`. The `data` argument is iteratble data type that + contains tuple of column and value, e.g. [(`cf:col`, 1), (`cf:col2`, 2)]. + + Note that unlike `counter_inc`, does not return value after incrementing. + + :param str row: the row key + :param list data: list of tuple for columns and values + """ + if data is not None and not isinstance(data, (list, tuple, izip)): + raise TypeError("'data' must be a iterable data types of tuple") + + self.connection.client.incrementRows( + [TIncrement(table=self.name, row=row, column=column, ammount=value) + for column, value in data]) + def counter_dec(self, row, column, value=1): """Atomically decrement (or increments) a counter column. From c7dd5622209eea83d6415980fd4d9446129616fe Mon Sep 17 00:00:00 2001 From: Kwangseob Kim Date: Sun, 3 May 2015 22:08:56 +0900 Subject: [PATCH 2/6] - Correct typo/PEP8 style - Renaming method counter_incs to counters_inc - Add nose tests for counters_inc --- happybase/table.py | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/happybase/table.py b/happybase/table.py index f35c49c..a142cb0 100644 --- a/happybase/table.py +++ b/happybase/table.py @@ -559,14 +559,27 @@ def counter_inc(self, row, column, value=1): return self.connection.client.atomicIncrement( self.name, row, column, value) - def counter_incs(self, row, data): + def counter_dec(self, row, column, value=1): + """Atomically decrement (or increments) a counter column. + + This method is a shortcut for calling :py:meth:`Table.counter_inc` with + the value negated. + + :return: counter value after decrementing + :rtype: int + """ + return self.counter_inc(row, column, -value) + + def counters_inc(self, row, data): """ - This method increments of decrements the counter columns in the row + This method increments (or decrements) the counter columns in the row specified by `row`. The `data` argument is iteratble data type that - contains tuple of column and value, e.g. [(`cf:col`, 1), (`cf:col2`, 2)]. + contains tuple of column and value, e.g. + [(`cf:col`, 1), (`cf:col2`, 2)]. - Note that unlike `counter_inc`, does not return value after incrementing. + Note that unlike `counter_inc`, does not return value after + incrementing. :param str row: the row key :param list data: list of tuple for columns and values @@ -577,14 +590,3 @@ def counter_incs(self, row, data): self.connection.client.incrementRows( [TIncrement(table=self.name, row=row, column=column, ammount=value) for column, value in data]) - - def counter_dec(self, row, column, value=1): - """Atomically decrement (or increments) a counter column. - - This method is a shortcut for calling :py:meth:`Table.counter_inc` with - the value negated. - - :return: counter value after decrementing - :rtype: int - """ - return self.counter_inc(row, column, -value) From 6c9a2e6db7c2aa023478403535e429dc91ae496b Mon Sep 17 00:00:00 2001 From: Kwangseob Kim Date: Sun, 3 May 2015 22:08:56 +0900 Subject: [PATCH 3/6] - Correct typo/PEP8 style - Renaming method counter_incs to counters_inc - Add nose tests for counters_inc --- happybase/table.py | 32 +++++++++++++++++--------------- tests/test_api.py | 20 ++++++++++++++++++++ 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/happybase/table.py b/happybase/table.py index f35c49c..a142cb0 100644 --- a/happybase/table.py +++ b/happybase/table.py @@ -559,14 +559,27 @@ def counter_inc(self, row, column, value=1): return self.connection.client.atomicIncrement( self.name, row, column, value) - def counter_incs(self, row, data): + def counter_dec(self, row, column, value=1): + """Atomically decrement (or increments) a counter column. + + This method is a shortcut for calling :py:meth:`Table.counter_inc` with + the value negated. + + :return: counter value after decrementing + :rtype: int + """ + return self.counter_inc(row, column, -value) + + def counters_inc(self, row, data): """ - This method increments of decrements the counter columns in the row + This method increments (or decrements) the counter columns in the row specified by `row`. The `data` argument is iteratble data type that - contains tuple of column and value, e.g. [(`cf:col`, 1), (`cf:col2`, 2)]. + contains tuple of column and value, e.g. + [(`cf:col`, 1), (`cf:col2`, 2)]. - Note that unlike `counter_inc`, does not return value after incrementing. + Note that unlike `counter_inc`, does not return value after + incrementing. :param str row: the row key :param list data: list of tuple for columns and values @@ -577,14 +590,3 @@ def counter_incs(self, row, data): self.connection.client.incrementRows( [TIncrement(table=self.name, row=row, column=column, ammount=value) for column, value in data]) - - def counter_dec(self, row, column, value=1): - """Atomically decrement (or increments) a counter column. - - This method is a shortcut for calling :py:meth:`Table.counter_inc` with - the value negated. - - :return: counter value after decrementing - :rtype: int - """ - return self.counter_inc(row, column, -value) diff --git a/tests/test_api.py b/tests/test_api.py index 292ee3f..77b03ef 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -183,6 +183,26 @@ def test_atomic_counters(): assert_equal(10, table.counter_dec(row, column, -7)) +def test_multiple_counters(): + row = 'row-with-counters' + columns = ['cf1:counter1', 'cf1:counter2', 'cf1:counter3'] + + table.counters_inc(row, zip(columns, [0, 0, 0])) + assert_equal([0, 0, 0], [table.counter_get(row, c) for c in columns]) + + table.counters_inc(row, zip(columns, [1, 3, 5])) + assert_equal([1, 3, 5], [table.counter_get(row, c) for c in columns]) + + table.counters_inc(row, zip(columns, [-1, -3, -5])) + assert_equal([0, 0, 0], [table.counter_get(row, c) for c in columns]) + + for col, delta in zip(columns, [1, 3, 5]): + table.counters_inc(row, [(col, delta)]) + assert_equal(delta, table.counter_get(row, col)) + table.counter_dec(row, [(col, delta)]) + assert_equal(0, table.counter_get(row, col)) + + def test_batch(): with assert_raises(TypeError): table.batch(timestamp='invalid') From c5761f64c5be0d9b08db73def39f5e450010f9a4 Mon Sep 17 00:00:00 2001 From: Kwangseob Kim Date: Sun, 3 May 2015 22:27:33 +0900 Subject: [PATCH 4/6] Add more tests --- tests/test_api.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/test_api.py b/tests/test_api.py index 77b03ef..018f0c5 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -199,9 +199,17 @@ def test_multiple_counters(): for col, delta in zip(columns, [1, 3, 5]): table.counters_inc(row, [(col, delta)]) assert_equal(delta, table.counter_get(row, col)) - table.counter_dec(row, [(col, delta)]) + table.counter_dec(row, [(col, -delta)]) assert_equal(0, table.counter_get(row, col)) + table.counters_inc(row, zip(columns, [1, 3, 5])) + table.counters_inc(row, zip(columns, [1, 3, 5])) + assert_equal([2, 6, 10], [table.counter_get(row, c) for c in columns]) + + table.counters_inc(row, zip(columns, [-1, -3, -5])) + table.counters_inc(row, zip(columns, [-1, -3, -5])) + assert_equal([0, 0, 0], [table.counter_get(row, c) for c in columns]) + def test_batch(): with assert_raises(TypeError): From 3ab00d24469e7253c466ac048166cc05efba77df Mon Sep 17 00:00:00 2001 From: Kwangseob Kim Date: Fri, 8 May 2015 02:36:13 +0900 Subject: [PATCH 5/6] Change parameter type as dict from iteratble data types --- happybase/table.py | 13 ++++++------- tests/test_api.py | 16 ++++++++-------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/happybase/table.py b/happybase/table.py index a142cb0..9c33e93 100644 --- a/happybase/table.py +++ b/happybase/table.py @@ -3,7 +3,6 @@ """ import logging -from itertools import izip from numbers import Integral from operator import attrgetter from struct import Struct @@ -574,19 +573,19 @@ def counters_inc(self, row, data): """ This method increments (or decrements) the counter columns in the row - specified by `row`. The `data` argument is iteratble data type that - contains tuple of column and value, e.g. - [(`cf:col`, 1), (`cf:col2`, 2)]. + specified by `row`. The `data` argument is a dictionary that + maps columns and its counter values, e.g. + {`cf:col`: 1, `cf:col2`: 2}. Note that unlike `counter_inc`, does not return value after incrementing. :param str row: the row key - :param list data: list of tuple for columns and values + :param dict data: the dictionary maps columns and tis counter values """ - if data is not None and not isinstance(data, (list, tuple, izip)): + if data is not None and not isinstance(data, dict): raise TypeError("'data' must be a iterable data types of tuple") self.connection.client.incrementRows( [TIncrement(table=self.name, row=row, column=column, ammount=value) - for column, value in data]) + for column, value in data.iteritems()]) diff --git a/tests/test_api.py b/tests/test_api.py index 018f0c5..79ea2c0 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -187,27 +187,27 @@ def test_multiple_counters(): row = 'row-with-counters' columns = ['cf1:counter1', 'cf1:counter2', 'cf1:counter3'] - table.counters_inc(row, zip(columns, [0, 0, 0])) + table.counters_inc(row, dict(zip(columns, [0, 0, 0]))) assert_equal([0, 0, 0], [table.counter_get(row, c) for c in columns]) - table.counters_inc(row, zip(columns, [1, 3, 5])) + table.counters_inc(row, dict(zip(columns, [1, 3, 5]))) assert_equal([1, 3, 5], [table.counter_get(row, c) for c in columns]) - table.counters_inc(row, zip(columns, [-1, -3, -5])) + table.counters_inc(row, dict(zip(columns, [-1, -3, -5]))) assert_equal([0, 0, 0], [table.counter_get(row, c) for c in columns]) - for col, delta in zip(columns, [1, 3, 5]): + for col, delta in dict(zip(columns, [1, 3, 5])): table.counters_inc(row, [(col, delta)]) assert_equal(delta, table.counter_get(row, col)) table.counter_dec(row, [(col, -delta)]) assert_equal(0, table.counter_get(row, col)) - table.counters_inc(row, zip(columns, [1, 3, 5])) - table.counters_inc(row, zip(columns, [1, 3, 5])) + table.counters_inc(row, dict(zip(columns, [1, 3, 5]))) + table.counters_inc(row, dict(zip(columns, [1, 3, 5]))) assert_equal([2, 6, 10], [table.counter_get(row, c) for c in columns]) - table.counters_inc(row, zip(columns, [-1, -3, -5])) - table.counters_inc(row, zip(columns, [-1, -3, -5])) + table.counters_inc(row, dict(zip(columns, [-1, -3, -5]))) + table.counters_inc(row, dict(zip(columns, [-1, -3, -5]))) assert_equal([0, 0, 0], [table.counter_get(row, c) for c in columns]) From ff5c525ad7030d594de9f34b2c3ca5cd5b88ef01 Mon Sep 17 00:00:00 2001 From: Kwangseob Kim Date: Fri, 8 May 2015 04:08:59 +0900 Subject: [PATCH 6/6] Correct typo --- happybase/table.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/happybase/table.py b/happybase/table.py index 9c33e93..9534217 100644 --- a/happybase/table.py +++ b/happybase/table.py @@ -575,16 +575,16 @@ def counters_inc(self, row, data): This method increments (or decrements) the counter columns in the row specified by `row`. The `data` argument is a dictionary that maps columns and its counter values, e.g. - {`cf:col`: 1, `cf:col2`: 2}. + {"cf:col": 1, "cf:col2": 2}. Note that unlike `counter_inc`, does not return value after incrementing. :param str row: the row key - :param dict data: the dictionary maps columns and tis counter values + :param dict data: the dictionary that maps columns to numeric counter values """ - if data is not None and not isinstance(data, dict): - raise TypeError("'data' must be a iterable data types of tuple") + if not isinstance(data, dict): + raise TypeError("'data' must be a dictionary") self.connection.client.incrementRows( [TIncrement(table=self.name, row=row, column=column, ammount=value)