Skip to content

Commit 4c1c2c1

Browse files
committed
Merge pull request #1545 from dhermes/happy-base-init-docs
Adding helpful documentation to HappyBase package init.
2 parents 03dd96f + a39a0fa commit 4c1c2c1

File tree

3 files changed

+155
-13
lines changed

3 files changed

+155
-13
lines changed

gcloud/bigtable/happybase/__init__.py

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,138 @@
1616
1717
This package is intended to emulate the HappyBase library using
1818
Google Cloud Bigtable as the backing store.
19+
20+
Differences in Public API
21+
-------------------------
22+
23+
Some concepts from HBase/Thrift do not map directly to the Cloud
24+
Bigtable API. As a result, the following instance methods and functions
25+
could not be implemented:
26+
27+
* :meth:`.Connection.enable_table` - no concept of enabled/disabled
28+
* :meth:`.Connection.disable_table` - no concept of enabled/disabled
29+
* :meth:`.Connection.is_table_enabled` - no concept of enabled/disabled
30+
* :meth:`.Connection.compact_table` - table storage is opaque to user
31+
* :func:`make_row() <gcloud.bigtable.happybase.table.make_row>` - helper
32+
needed for Thrift library
33+
* :func:`make_ordered_row() <gcloud.bigtable.happybase.table.make_ordered_row>`
34+
- helper needed for Thrift library
35+
* :meth:`Table.regions() <gcloud.bigtable.happybase.table.Table.regions>`
36+
- tables in Cloud Bigtable do not expose internal storage details
37+
* :meth:`Table.counter_set() \
38+
<gcloud.bigtable.happybase.table.Table.counter_set>` - method can't
39+
be atomic, so we disable it
40+
* The ``__version__`` value for the HappyBase package is :data:`None`.
41+
However, it's worth nothing this implementation was based off HappyBase
42+
0.9.
43+
44+
In addition, many of the constants from :mod:`.connection` are specific
45+
to HBase and are defined as :data:`None` in our module:
46+
47+
* ``COMPAT_MODES``
48+
* ``THRIFT_TRANSPORTS``
49+
* ``THRIFT_PROTOCOLS``
50+
* ``DEFAULT_HOST``
51+
* ``DEFAULT_PORT``
52+
* ``DEFAULT_TRANSPORT``
53+
* ``DEFAULT_COMPAT``
54+
* ``DEFAULT_PROTOCOL``
55+
56+
Two of these ``DEFAULT_HOST`` and ``DEFAULT_PORT``, are even imported in
57+
the main :mod:`happybase <gcloud.bigtable.happybase>` package.
58+
59+
Finally, we do not provide the ``util`` module. Though it is public in the
60+
HappyBase library, it provides no core functionality.
61+
62+
API Behavior Changes
63+
--------------------
64+
65+
* Since there is no concept of an enabled / disabled table, calling
66+
:meth:`.Connection.delete_table` with ``disable=True`` can't be supported.
67+
Using that argument will result in a warning.
68+
* The :class:`.Connection` constructor **disables** the use of several
69+
arguments and will print a warning if any of them are passed in as keyword
70+
arguments. The arguments are:
71+
72+
* ``host``
73+
* ``port``
74+
* ``compat``
75+
* ``transport``
76+
* ``protocol``
77+
* In order to make :class:`.Connection` compatible with Cloud Bigtable, we
78+
add a ``cluster`` keyword argument to allow user's to pass in their own
79+
:class:`.Cluster` (which they can construct beforehand).
80+
81+
For example:
82+
83+
.. code:: python
84+
85+
from gcloud.bigtable.client import Client
86+
client = Client(project=PROJECT_ID, admin=True)
87+
cluster = client.cluster(zone, cluster_id)
88+
cluster.reload()
89+
90+
from gcloud.bigtable.happybase import Connection
91+
connection = Connection(cluster=cluster)
92+
93+
* Any uses of the ``wal`` (Write Ahead Log) argument will result in a
94+
warning as well. This includes uses in:
95+
96+
* :class:`.Batch` constructor
97+
* :meth:`.Batch.put`
98+
* :meth:`.Batch.delete`
99+
* :meth:`Table.put() <gcloud.bigtable.happybase.table.Table.put>`
100+
* :meth:`Table.delete() <gcloud.bigtable.happybase.table.Table.delete>`
101+
* :meth:`Table.batch() <gcloud.bigtable.happybase.table.Table.batch>` factory
102+
* When calling :meth:`.Connection.create_table`, the majority of HBase column
103+
family options cannot be used. Among
104+
105+
* ``max_versions``
106+
* ``compression``
107+
* ``in_memory``
108+
* ``bloom_filter_type``
109+
* ``bloom_filter_vector_size``
110+
* ``bloom_filter_nb_hashes``
111+
* ``block_cache_enabled``
112+
* ``time_to_live``
113+
114+
Only ``max_versions`` and ``time_to_live`` are availabe in Cloud Bigtable
115+
(as
116+
:class:`MaxVersionsGCRule <gcloud.bigtable.column_family.MaxVersionsGCRule>`
117+
and
118+
`MaxAgeGCRule <gcloud.bigtable.column_family.MaxAgeGCRule>`).
119+
120+
In addition to using a dictionary for specifying column family options,
121+
we also accept instances of :class:`.GarbageCollectionRule` or subclasses.
122+
* :meth:`Table.scan() <gcloud.bigtable.happybase.table.Table.scan>` no longer
123+
accepts the following arguments (which will result in a warning):
124+
125+
* ``batch_size``
126+
* ``scan_batching``
127+
* ``sorted_columns``
128+
129+
* Using a HBase filter string in
130+
:meth:`Table.scan() <gcloud.bigtable.happybase.table.Table.scan>` is
131+
not possible with Cloud Bigtable and will result in a
132+
:class:`TypeError <exceptions.TypeError>`. However, the method now accepts
133+
instances of :class:`.RowFilter` and subclasses.
134+
* :meth:`.Batch.delete` (and hence
135+
:meth:`Table.delete() <gcloud.bigtable.happybase.table.Table.delete>`)
136+
will fail with a :class:`ValueError <exceptions.ValueError>` when either a
137+
row or column family delete is attempted with a ``timestamp``. This is
138+
because the Cloud Bigtable API uses the ``DeleteFromFamily`` and
139+
``DeleteFromRow`` mutations for these deletes, and neither of these
140+
mutations support a timestamp.
19141
"""
142+
143+
from gcloud.bigtable.happybase.batch import Batch
144+
from gcloud.bigtable.happybase.connection import Connection
145+
from gcloud.bigtable.happybase.connection import DEFAULT_HOST
146+
from gcloud.bigtable.happybase.connection import DEFAULT_PORT
147+
from gcloud.bigtable.happybase.pool import ConnectionPool
148+
from gcloud.bigtable.happybase.pool import NoConnectionsAvailable
149+
from gcloud.bigtable.happybase.table import Table
150+
151+
152+
# Values from HappyBase that we don't reproduce / are not relevant.
153+
__version__ = None

gcloud/bigtable/happybase/connection.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@
4141

4242
_LEGACY_ARGS = frozenset(('host', 'port', 'compat', 'transport', 'protocol'))
4343
_WARN = warnings.warn
44+
_DISABLE_DELETE_MSG = ('The disable argument should not be used in '
45+
'delete_table(). Cloud Bigtable has no concept '
46+
'of enabled / disabled tables.')
4447

4548

4649
def _get_cluster(timeout=None):
@@ -349,14 +352,9 @@ def delete_table(self, name, disable=False):
349352
is provided for compatibility with HappyBase, but is
350353
not relevant for Cloud Bigtable since it has no concept
351354
of enabled / disabled tables.
352-
353-
:raises: :class:`ValueError <exceptions.ValueError>`
354-
if ``disable=True``.
355355
"""
356356
if disable:
357-
raise ValueError('The disable argument should not be used in '
358-
'delete_table(). Cloud Bigtable has no concept '
359-
'of enabled / disabled tables.')
357+
_WARN(_DISABLE_DELETE_MSG)
360358

361359
name = self._table_name(name)
362360
_LowLevelTable(name, self._cluster).delete()

gcloud/bigtable/happybase/test_connection.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ def test_create_table_bad_value(self):
395395
with self.assertRaises(ValueError):
396396
connection.create_table(name, families)
397397

398-
def test_delete_table(self):
398+
def _delete_table_helper(self, disable=False):
399399
from gcloud._testing import _Monkey
400400
from gcloud.bigtable.happybase import connection as MUT
401401

@@ -411,20 +411,30 @@ def make_table(*args, **kwargs):
411411

412412
name = 'table-name'
413413
with _Monkey(MUT, _LowLevelTable=make_table):
414-
connection.delete_table(name)
414+
connection.delete_table(name, disable=disable)
415415

416416
# Just one table would have been created.
417417
table_instance, = tables_created
418418
self.assertEqual(table_instance.args, (name, cluster))
419419
self.assertEqual(table_instance.kwargs, {})
420420
self.assertEqual(table_instance.delete_calls, 1)
421421

422+
def test_delete_table(self):
423+
self._delete_table_helper()
424+
422425
def test_delete_table_disable(self):
423-
cluster = _Cluster() # Avoid implicit environ check.
424-
connection = self._makeOne(autoconnect=False, cluster=cluster)
425-
name = 'table-name'
426-
with self.assertRaises(ValueError):
427-
connection.delete_table(name, disable=True)
426+
from gcloud._testing import _Monkey
427+
from gcloud.bigtable.happybase import connection as MUT
428+
429+
warned = []
430+
431+
def mock_warn(msg):
432+
warned.append(msg)
433+
434+
with _Monkey(MUT, _WARN=mock_warn):
435+
self._delete_table_helper(disable=True)
436+
437+
self.assertEqual(warned, [MUT._DISABLE_DELETE_MSG])
428438

429439
def test_enable_table(self):
430440
cluster = _Cluster() # Avoid implicit environ check.

0 commit comments

Comments
 (0)