diff options
author | Wouter Bolsterlee <wouter@bolsterl.ee> | 2016-07-28 09:43:46 +0200 |
---|---|---|
committer | Wouter Bolsterlee <wouter@bolsterl.ee> | 2016-07-28 09:43:46 +0200 |
commit | eae66a37fa13f8dcbe987df9b10a57ce6b691053 (patch) | |
tree | 7435efaec538bd6f4a3d360b2d6830f3618ffb3c | |
parent | ec5178d9b192cd0bc8641c804eeffc463b8db093 (diff) | |
download | happybase-eae66a37fa13f8dcbe987df9b10a57ce6b691053.tar.gz |
Use byte strings and print() function in example code
-rw-r--r-- | doc/index.rst | 18 | ||||
-rw-r--r-- | doc/user.rst | 127 | ||||
-rw-r--r-- | happybase/table.py | 17 |
3 files changed, 82 insertions, 80 deletions
diff --git a/doc/index.rst b/doc/index.rst index a7aa16c..705f09f 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -39,19 +39,19 @@ The example below illustrates basic usage of the library. The :doc:`user guide connection = happybase.Connection('hostname') table = connection.table('table-name') - table.put('row-key', {'family:qual1': 'value1', - 'family:qual2': 'value2'}) + table.put(b'row-key', {b'family:qual1': b'value1', + b'family:qual2': b'value2'}) - row = table.row('row-key') - print row['family:qual1'] # prints 'value1' + row = table.row(b'row-key') + print(row[b'family:qual1']) # prints 'value1' - for key, data in table.rows(['row-key-1', 'row-key-2']): - print key, data # prints row key and data for each row + for key, data in table.rows([b'row-key-1', b'row-key-2']): + print(key, data) # prints row key and data for each row - for key, data in table.scan(row_prefix='row'): - print key, data # prints 'value1' and 'value2' + for key, data in table.scan(row_prefix=b'row'): + print(key, data) # prints 'value1' and 'value2' - row = table.delete('row-key') + row = table.delete(b'row-key') Core documentation diff --git a/doc/user.rst b/doc/user.rst index e2e327f..b526072 100644 --- a/doc/user.rst +++ b/doc/user.rst @@ -50,7 +50,7 @@ The :py:class:`Connection` class provides the main entry point to interact with HBase. For instance, to list the available tables, use :py:meth:`Connection.tables`:: - print connection.tables() + print(connection.tables()) Most other methods on the :py:class:`Connection` class are intended for system management tasks like creating, dropping, enabling and disabling tables. See the @@ -126,8 +126,8 @@ At this point, :py:meth:`Connection.tables` no longer includes tables in other ‘namespaces’. HappyBase will only return tables with a ``myproject_`` prefix, and will also remove the prefix transparently when returning results, e.g.:: - print connection.tables() # Table "myproject_XYZ" in HBase will be - # returned as simply "XYZ" + print(connection.tables()) # Table "myproject_XYZ" in HBase will be + # returned as simply "XYZ" This also applies to other methods that take table names, such as :py:meth:`Connection.table`:: @@ -158,27 +158,27 @@ table in HBase. The most basic one is :py:meth:`Table.row`, which retrieves a single row from the table, and returns it as a dictionary mapping columns to values:: - row = table.row('row-key') - print row['cf1:col1'] # prints the value of cf1:col1 + row = table.row(b'row-key') + print(row[b'cf1:col1']) # prints the value of cf1:col1 The :py:meth:`Table.rows` method works just like :py:meth:`Table.row`, but takes multiple row keys and returns those as `(key, data)` tuples:: - rows = table.rows(['row-key-1', 'row-key-2']) + rows = table.rows([b'row-key-1', b'row-key-2']) for key, data in rows: - print key, data + print(key, data) If you want the results that :py:meth:`Table.rows` returns as a dictionary or ordered dictionary, you will have to do this yourself. This is really easy though, since the return value can be passed directly to the dictionary constructor. For a normal dictionary, order is lost:: - rows_as_dict = dict(table.rows(['row-key-1', 'row-key-2'])) + rows_as_dict = dict(table.rows([b'row-key-1', b'row-key-2'])) …whereas for a :py:class:`OrderedDict`, order is preserved:: from collections import OrderedDict - rows_as_ordered_dict = OrderedDict(table.rows(['row-key-1', 'row-key-2'])) + rows_as_ordered_dict = OrderedDict(table.rows([b'row-key-1', b'row-key-2'])) Making more fine-grained selections @@ -190,16 +190,16 @@ improved by specifying those columns explicitly to :py:meth:`Table.row` and :py:meth:`Table.rows`. The `columns` argument takes a list (or tuple) of column names:: - row = table.row('row-key', columns=['cf1:col1', 'cf1:col2']) - print row['cf1:col1'] - print row['cf1:col2'] + row = table.row(b'row-key', columns=[b'cf1:col1', b'cf1:col2']) + print(row[b'cf1:col1']) + print(row[b'cf1:col2']) Instead of providing both a column family and a column qualifier, items in the `columns` argument may also be just a column family, which means that all columns from that column family will be retrieved. For example, to get all columns and values in the column family `cf1`, use this:: - row = table.row('row-key', columns=['cf1']) + row = table.row(b'row-key', columns=[b'cf1']) In HBase, each cell has a timestamp attached to it. In case you don't want to work with the latest version of data stored in HBase, the methods that retrieve @@ -207,15 +207,15 @@ data from the database, e.g. :py:meth:`Table.row`, all accept a `timestamp` argument that specifies that the results should be restricted to values with a timestamp up to the specified timestamp:: - row = table.row('row-key', timestamp=123456789) + row = table.row(b'row-key', timestamp=123456789) By default, HappyBase does not include timestamps in the results it returns. In your application needs access to the timestamps, simply set the `include_timestamp` argument to ``True``. Now, each cell in the result will be returned as a `(value, timestamp)` tuple instead of just a value:: - row = table.row('row-key', columns=['cf1:col1'], include_timestamp=True) - value, timestamp = row['cf1:col1'] + row = table.row(b'row-key', columns=[b'cf1:col1'], include_timestamp=True) + value, timestamp = row[b'cf1:col1'] HBase supports storing multiple versions of the same cell. This can be configured for each column family. To retrieve all versions of a column for a @@ -225,13 +225,13 @@ argument specifies the maximum number of versions to return. Just like the methods that retrieve rows, the `include_timestamp` argument determines whether timestamps are included in the result. Example:: - values = table.cells('row-key', 'cf1:col1', versions=2) + values = table.cells(b'row-key', b'cf1:col1', versions=2) for value in values: - print "Cell data: %s" % value + print("Cell data: {}".format(value)) - cells = table.cells('row-key', 'cf1:col1', versions=3, include_timestamp=True) + cells = table.cells(b'row-key', b'cf1:col1', versions=3, include_timestamp=True) for value, timestamp in cells: - print "Cell data at %d: %s" % (timestamp, value) + print("Cell data at {}: {}".format(timestamp, value)) Note that the result may contain fewer cells than requested. The cell may just have fewer versions, or you may have requested more versions than HBase keeps @@ -246,32 +246,32 @@ efficiently iterated over using a table scanner, created using looks like this:: for key, data in table.scan(): - print key, data + print(key, data) Doing full table scans like in the example above is prohibitively expensive in practice. Scans can be restricted in several ways to make more selective range queries. One way is to specify start or stop keys, or both. To iterate over all rows from row `aaa` to the end of the table:: - for key, data in table.scan(row_start='aaa'): - print key, data + for key, data in table.scan(row_start=b'aaa'): + print(key, data) To iterate over all rows from the start of the table up to row `xyz`, use this:: - for key, data in table.scan(row_stop='xyz'): - print key, data + for key, data in table.scan(row_stop=b'xyz'): + print(key, data) To iterate over all rows between row `aaa` (included) and `xyz` (not included), supply both:: - for key, data in table.scan(row_start='aaa', row_stop='xyz'): - print key, data + for key, data in table.scan(row_start=b'aaa', row_stop=b'xyz'): + print(key, data) An alternative is to use a key prefix. For example, to iterate over all rows starting with `abc`:: - for key, data in table.scan(row_prefix='abc'): - print key, data + for key, data in table.scan(row_prefix=b'abc'): + print(key, data) The scanner examples above only limit the results by row key using the `row_start`, `row_stop`, and `row_prefix` arguments, but scanners can also @@ -315,12 +315,12 @@ To store a single cell of data in our table, we can use :py:meth:`Table.put`, which takes the row key, and the data to store. The data should be a dictionary mapping the column name to a value:: - table.put('row-key', {'cf:col1': 'value1', - 'cf:col2': 'value2'}) + table.put(b'row-key', {b'cf:col1': b'value1', + b'cf:col2': b'value2'}) Use the `timestamp` argument if you want to provide timestamps explicitly:: - table.put('row-key', {'cf:col1': 'value1'}, timestamp=123456789) + table.put(b'row-key', {b'cf:col1': b'value1'}, timestamp=123456789) If omitted, HBase defaults to the current system time. @@ -330,12 +330,12 @@ Deleting data The :py:meth:`Table.delete` method deletes data from a table. To delete a complete row, just specify the row key:: - table.delete('row-key') + table.delete(b'row-key') To delete one or more columns instead of a complete row, also specify the `columns` argument:: - table.delete('row-key', columns=['cf1:col1', 'cf1:col2']) + table.delete(b'row-key', columns=[b'cf1:col1', b'cf1:col2']) The optional `timestamp` argument restricts the delete operation to data up to the specified timestamp. @@ -353,10 +353,10 @@ delete methods, just like the :py:class:`Table` class, but the changes are sent to the server in a single round-trip using :py:meth:`Batch.send`:: b = table.batch() - b.put('row-key-1', {'cf:col1': 'value1', 'cf:col2': 'value2'}) - b.put('row-key-2', {'cf:col2': 'value2', 'cf:col3': 'value3'}) - b.put('row-key-3', {'cf:col3': 'value3', 'cf:col4': 'value4'}) - b.delete('row-key-4') + b.put(b'row-key-1', {b'cf:col1': b'value1', b'cf:col2': b'value2'}) + b.put(b'row-key-2', {b'cf:col2': b'value2', b'cf:col3': b'value3'}) + b.put(b'row-key-3', {b'cf:col3': b'value3', b'cf:col4': b'value4'}) + b.delete(b'row-key-4') b.send() .. note:: @@ -379,10 +379,10 @@ useful in combination with Python's ``with`` construct. The example above can be simplified to read:: with table.batch() as b: - b.put('row-key-1', {'cf:col1': 'value1', 'cf:col2': 'value2'}) - b.put('row-key-2', {'cf:col2': 'value2', 'cf:col3': 'value3'}) - b.put('row-key-3', {'cf:col3': 'value3', 'cf:col4': 'value4'}) - b.delete('row-key-4') + b.put(b'row-key-1', {b'cf:col1': b'value1', b'cf:col2': b'value2'}) + b.put(b'row-key-2', {b'cf:col2': b'value2', b'cf:col3': b'value3'}) + b.put(b'row-key-3', {b'cf:col3': b'value3', b'cf:col4': b'value4'}) + b.delete(b'row-key-4') As you can see, there is no call to :py:meth:`Batch.send` anymore. The batch is automatically applied when the ``with`` code block terminates, even in case of @@ -393,13 +393,13 @@ manager this would look something like this:: b = table.batch() try: - b.put('row-key-1', {'cf:col1': 'value1', 'cf:col2': 'value2'}) - b.put('row-key-2', {'cf:col2': 'value2', 'cf:col3': 'value3'}) - b.put('row-key-3', {'cf:col3': 'value3', 'cf:col4': 'value4'}) - b.delete('row-key-4') + b.put(b'row-key-1', {b'cf:col1': b'value1', b'cf:col2': b'value2'}) + b.put(b'row-key-2', {b'cf:col2': b'value2', b'cf:col3': b'value3'}) + b.put(b'row-key-3', {b'cf:col3': b'value3', b'cf:col4': b'value4'}) + b.delete(b'row-key-4') raise ValueError("Something went wrong!") except ValueError as e: - # error handling goes here; nothing is sent to HBase + # error handling goes here; nothing will be sent to HBase pass else: # no exceptions; send data @@ -410,10 +410,10 @@ Obtaining the same behaviour is easier using a ``with`` block. The try: with table.batch(transaction=True) as b: - b.put('row-key-1', {'cf:col1': 'value1', 'cf:col2': 'value2'}) - b.put('row-key-2', {'cf:col2': 'value2', 'cf:col3': 'value3'}) - b.put('row-key-3', {'cf:col3': 'value3', 'cf:col4': 'value4'}) - b.delete('row-key-4') + b.put(b'row-key-1', {b'cf:col1': b'value1', b'cf:col2': b'value2'}) + b.put(b'row-key-2', {b'cf:col2': b'value2', b'cf:col3': b'value3'}) + b.put(b'row-key-3', {b'cf:col3': b'value3', b'cf:col4': b'value4'}) + b.delete(b'row-key-4') raise ValueError("Something went wrong!") except ValueError: # error handling goes here; nothing is sent to HBase @@ -435,8 +435,10 @@ example, this will result in three round-trips to the server (two batches with with table.batch(batch_size=1000) as b: for i in range(1200): # this put() will result in two mutations (two cells) - b.put('row-%04d' % i, {'cf1:col1': 'v1', - 'cf1:col2': 'v2',}) + b.put(b'row-%04d'.format(i), { + b'cf1:col1': b'v1', + b'cf1:col2': b'v2', + }) The appropriate `batch_size` is very application-specific since it depends on the data size, so just experiment to see how different sizes work for your @@ -451,23 +453,23 @@ interpreted as big-endian 64-bit signed integers by HBase. Counters are automatically initialised to 0 upon first use. When incrementing or decrementing a counter, the value after modification is returned. Example:: - print table.counter_inc('row-key', 'cf1:counter') # prints 1 - print table.counter_inc('row-key', 'cf1:counter') # prints 2 - print table.counter_inc('row-key', 'cf1:counter') # prints 3 + print(table.counter_inc(b'row-key', b'cf1:counter')) # prints 1 + print(table.counter_inc(b'row-key', b'cf1:counter')) # prints 2 + print(table.counter_inc(b'row-key', b'cf1:counter')) # prints 3 - print table.counter_dec('row-key', 'cf1:counter') # prints 2 + print(table.counter_dec(b'row-key', b'cf1:counter')) # prints 2 The optional `value` argument specifies how much to increment or decrement by:: - print table.counter_inc('row-key', 'cf1:counter', value=3) # prints 5 + print(table.counter_inc(b'row-key', b'cf1:counter', value=3)) # prints 5 While counters are typically used with the increment and decrement functions shown above, the :py:meth:`Table.counter_get` and :py:meth:`Table.counter_set` methods can be used to retrieve or set a counter value directly:: - print table.counter_get('row-key', 'cf1:counter') # prints 5 + print(table.counter_get(b'row-key', b'cf1:counter')) # prints 5 - table.counter_set('row-key', 'cf1:counter', 12) + table.counter_set(b'row-key', b'cf1:counter', 12) .. note:: @@ -477,7 +479,6 @@ methods can be used to retrieve or set a counter value directly:: :py:meth:`~Table.counter_dec` instead! - Using the connection pool ========================= @@ -514,7 +515,7 @@ are actually returned to the pool after use. Example:: pool = happybase.ConnectionPool(size=3, host='...') with pool.connection() as connection: - print connection.tables() + print(connection.tables()) .. warning:: @@ -530,7 +531,7 @@ data outside the ``with`` block:: with pool.connection() as connection: table = connection.table('table-name') - row = table.row('row-key') + row = table.row(b'row-key') process_data(row) diff --git a/happybase/table.py b/happybase/table.py index 8866109..4400723 100644 --- a/happybase/table.py +++ b/happybase/table.py @@ -93,12 +93,13 @@ class Table(object): argument and returns the columns and values for this row as a dictionary. - The `row` argument is the row key of the row. If the `columns` argument - is specified, only the values for these columns will be returned - instead of all available columns. The `columns` argument should be - a list or tuple containing strings. Each name can be a column family, - such as `cf1` or `cf1:` (the trailing colon is not required), or - a column family with a qualifier, such as `cf1:col1`. + The `row` argument is the row key of the row. If the `columns` + argument is specified, only the values for these columns will be + returned instead of all available columns. The `columns` + argument should be a list or tuple containing byte strings. Each + name can be a column family, such as ``b'cf1'`` or ``b'cf1:'`` + (the trailing colon is not required), or a column family with a + qualifier, such as ``b'cf1:col1'``. If specified, the `timestamp` argument specifies the maximum version that results may have. The `include_timestamp` argument specifies @@ -424,8 +425,8 @@ class Table(object): This method stores the data in the `data` argument for the row specified by `row`. The `data` argument is dictionary that maps columns to values. Column names must include a family and qualifier part, e.g. - `cf:col`, though the qualifier part may be the empty string, e.g. - `cf:`. + ``b'cf:col'``, though the qualifier part may be the empty string, e.g. + ``b'cf:'``. Note that, in many situations, :py:meth:`batch()` is a more appropriate method to manipulate data. |