From ba3f59642d2d5aa5a3b449822945cfe0dc007dd5 Mon Sep 17 00:00:00 2001 From: Kevin Zheng Date: Wed, 30 Apr 2025 18:39:54 +0000 Subject: [PATCH 1/4] feat: Prototyped handwritten layer --- .../bigtable/admin_v2/overlay/__init__.py | 38 ++++ .../admin_v2/overlay/services/__init__.py | 13 ++ .../services/bigtable_table_admin/__init__.py | 21 ++ .../services/bigtable_table_admin/client.py | 193 ++++++++++++++++++ .../admin_v2/overlay/types/__init__.py | 39 ++++ .../admin_v2/overlay/types/consistency.py | 60 ++++++ .../admin_v2/overlay/types/gc_rule.py | 160 +++++++++++++++ .../admin_v2/overlay/types/restore_table.py | 64 ++++++ 8 files changed, 588 insertions(+) create mode 100644 google/cloud/bigtable/admin_v2/overlay/__init__.py create mode 100644 google/cloud/bigtable/admin_v2/overlay/services/__init__.py create mode 100644 google/cloud/bigtable/admin_v2/overlay/services/bigtable_table_admin/__init__.py create mode 100644 google/cloud/bigtable/admin_v2/overlay/services/bigtable_table_admin/client.py create mode 100644 google/cloud/bigtable/admin_v2/overlay/types/__init__.py create mode 100644 google/cloud/bigtable/admin_v2/overlay/types/consistency.py create mode 100644 google/cloud/bigtable/admin_v2/overlay/types/gc_rule.py create mode 100644 google/cloud/bigtable/admin_v2/overlay/types/restore_table.py diff --git a/google/cloud/bigtable/admin_v2/overlay/__init__.py b/google/cloud/bigtable/admin_v2/overlay/__init__.py new file mode 100644 index 000000000..a26848416 --- /dev/null +++ b/google/cloud/bigtable/admin_v2/overlay/__init__.py @@ -0,0 +1,38 @@ +# Copyright 2025 Google LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from .types import ( + BaseGarbageCollectionRule, + MaxAgeGarbageCollectionRule, + MaxNumVersionsGarbageCollectionRule, + UnionGarbageCollectionRule, + IntersectionGarbageCollectionRule, + RestoreTableOperation, + CheckConsistencyPollingFuture, +) + +from .services.bigtable_table_admin import ( + BigtableTableAdminClient, +) + +__all__ = ( + "BaseGarbageCollectionRule", + "MaxAgeGarbageCollectionRule", + "MaxNumVersionsGarbageCollectionRule", + "UnionGarbageCollectionRule", + "IntersectionGarbageCollectionRule", + "RestoreTableOperation", + "CheckConsistencyPollingFuture", + "BigtableTableAdminClient" +) diff --git a/google/cloud/bigtable/admin_v2/overlay/services/__init__.py b/google/cloud/bigtable/admin_v2/overlay/services/__init__.py new file mode 100644 index 000000000..ab7686e26 --- /dev/null +++ b/google/cloud/bigtable/admin_v2/overlay/services/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2025 Google LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/google/cloud/bigtable/admin_v2/overlay/services/bigtable_table_admin/__init__.py b/google/cloud/bigtable/admin_v2/overlay/services/bigtable_table_admin/__init__.py new file mode 100644 index 000000000..6c7f49e21 --- /dev/null +++ b/google/cloud/bigtable/admin_v2/overlay/services/bigtable_table_admin/__init__.py @@ -0,0 +1,21 @@ +# Copyright 2025 Google LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# TODO: Add the async client after owlbot changes. + +from .client import BigtableTableAdminClient + +__all__ = ( + "BigtableTableAdminClient", +) diff --git a/google/cloud/bigtable/admin_v2/overlay/services/bigtable_table_admin/client.py b/google/cloud/bigtable/admin_v2/overlay/services/bigtable_table_admin/client.py new file mode 100644 index 000000000..8344393b7 --- /dev/null +++ b/google/cloud/bigtable/admin_v2/overlay/services/bigtable_table_admin/client.py @@ -0,0 +1,193 @@ +# Copyright 2025 Google LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# -*- coding: utf-8 -*- +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import functools + +from typing import Optional, Sequence, Tuple, Union +from google.api_core import gapic_v1 +from google.api_core import retry as retries + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object, None] # type: ignore + +from google.api_core import operation # type: ignore +from google.cloud.bigtable.admin_v2.types import bigtable_table_admin + +from google.cloud.bigtable.admin_v2.services.bigtable_table_admin import BaseBigtableTableAdminClient +from google.cloud.bigtable.admin_v2.overlay.types import consistency, restore_table + +class BigtableTableAdminClient(BaseBigtableTableAdminClient): + + def restore_table( + self, + request: Optional[Union[bigtable_table_admin.RestoreTableRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> restore_table.RestoreTableOperation: + r"""Create a new table by restoring from a completed backup. The + returned table [long-running + operation][google.longrunning.Operation] can be used to track + the progress of the operation, and to cancel it. The + [metadata][google.longrunning.Operation.metadata] field type is + [RestoreTableMetadata][google.bigtable.admin.v2.RestoreTableMetadata]. + The [response][google.longrunning.Operation.response] type is + [Table][google.bigtable.admin.v2.Table], if successful. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud.bigtable import admin_v2 + + def sample_restore_table(): + # Create a client + client = admin_v2.BigtableTableAdminClient() + + # Initialize request argument(s) + request = admin_v2.RestoreTableRequest( + backup="backup_value", + parent="parent_value", + table_id="table_id_value", + ) + + # Make the request + operation = client.restore_table(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + + # Handle the response + print(response) + + # Handle LRO2 + optimize_operation = operation.optimize_restore_table_operation() + + if optimize_operation: + print("Waiting for table optimization to complete...") + + response = optimize_operation.result() + + Args: + request (Union[google.cloud.bigtable.admin_v2.types.RestoreTableRequest, dict]): + The request object. The request for + [RestoreTable][google.bigtable.admin.v2.BigtableTableAdmin.RestoreTable]. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.cloud.bigtable.admin_v2.overlay.types.restore_table.RestoreTableOperation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.cloud.bigtable.admin_v2.types.Table` A collection of user data indexed by row, column, and timestamp. + Each table is served using the resources of its + parent cluster. + """ + operation = self._restore_table( + request=request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + restore_table_operation = restore_table.RestoreTableOperation(self._transport.operations_client, operation) + return restore_table_operation + + def await_consistency( + self, + request: Optional[ + Union[bigtable_table_admin.CheckConsistencyRequest, dict] + ] = None, + *, + name: Optional[str] = None, + consistency_token: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> consistency.CheckConsistencyPollingFuture: + + api_call = functools.partial( + self.check_consistency, + request, + name=name, + consistency_token=consistency_token, + timeout=timeout, + metadata=metadata, + ) + return consistency.CheckConsistencyPollingFuture(api_call, default_retry=retry) + + def await_replication( + self, + request: Optional[ + Union[bigtable_table_admin.GenerateConsistencyTokenRequest, dict] + ] = None, + *, + name: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> consistency.CheckConsistencyPollingFuture: + + generate_consistency_response = self.generate_consistency_token( + request, + name=name, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Create the CheckConsistencyRequest object. + check_consistency_request = bigtable_table_admin.CheckConsistencyRequest() + + # If the generate_consistency_token request is valid, there's a name in the request object + # or the name parameter. + if isinstance(request, dict): + check_consistency_request.name = request["name"] + elif isinstance(request, bigtable_table_admin.GenerateConsistencyTokenRequest): + check_consistency_request.name = request.name + else: + check_consistency_request.name = name + + check_consistency_request.consistency_token = generate_consistency_response.consistency_token + + return self.await_consistency(check_consistency_request, retry=retry, timeout=timeout, metadata=metadata) diff --git a/google/cloud/bigtable/admin_v2/overlay/types/__init__.py b/google/cloud/bigtable/admin_v2/overlay/types/__init__.py new file mode 100644 index 000000000..456f80d24 --- /dev/null +++ b/google/cloud/bigtable/admin_v2/overlay/types/__init__.py @@ -0,0 +1,39 @@ +# Copyright 2025 Google LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from .gc_rule import ( + BaseGarbageCollectionRule, + MaxAgeGarbageCollectionRule, + MaxNumVersionsGarbageCollectionRule, + UnionGarbageCollectionRule, + IntersectionGarbageCollectionRule, +) + +from .consistency import ( + CheckConsistencyPollingFuture, +) + +from .restore_table import ( + RestoreTableOperation, +) + +__all__ = ( + "BaseGarbageCollectionRule", + "MaxAgeGarbageCollectionRule", + "MaxNumVersionsGarbageCollectionRule", + "UnionGarbageCollectionRule", + "IntersectionGarbageCollectionRule", + "CheckConsistencyPollingFuture", + "RestoreTableOperation", +) \ No newline at end of file diff --git a/google/cloud/bigtable/admin_v2/overlay/types/consistency.py b/google/cloud/bigtable/admin_v2/overlay/types/consistency.py new file mode 100644 index 000000000..40e5e7591 --- /dev/null +++ b/google/cloud/bigtable/admin_v2/overlay/types/consistency.py @@ -0,0 +1,60 @@ +# Copyright 2025 Google LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import Union, Callable + +from google.api_core.future import polling +from google.api_core import gapic_v1 +from google.api_core import retry as retries + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object, None] # type: ignore + + +class CheckConsistencyPollingFuture(polling.PollingFuture): + def __init__(self, + check_consistency_call: Callable, + default_retry: OptionalRetry = gapic_v1.method.DEFAULT, + polling: retries.Retry = polling.DEFAULT_POLLING, + **kwargs): + super(CheckConsistencyPollingFuture, self).__init__(polling=polling, **kwargs) + + # Done is called with two different scenarios, retry is specified or not specified. + # API_call will be a functools partial with everything except retry specified because of + # that. + self._check_consistency_call = check_consistency_call + self._default_retry = default_retry + + def done(self, retry: OptionalRetry=None): + if self._result_set: + return True + + retry = retry or self._default_retry + + try: + check_consistency_response = self._check_consistency_call(retry=retry) + if check_consistency_response.consistent: + self.set_result(True) + + return check_consistency_response.consistent + except Exception as e: + self.set_exception(e) + + def cancel(self): + raise NotImplementedError("Cannot cancel consistency token operation") + + def cancelled(self): + raise NotImplementedError("Cannot cancel consistency token operation") diff --git a/google/cloud/bigtable/admin_v2/overlay/types/gc_rule.py b/google/cloud/bigtable/admin_v2/overlay/types/gc_rule.py new file mode 100644 index 000000000..9da092197 --- /dev/null +++ b/google/cloud/bigtable/admin_v2/overlay/types/gc_rule.py @@ -0,0 +1,160 @@ +# Copyright 2025 Google LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# TODO: Samples in docstrings will be slightly off. Fix this later. Also improve docstrings. + +import abc + +from google.protobuf import duration_pb2 +from google.cloud.bigtable.admin_v2.types import table as table_pb2 + + +class BaseGarbageCollectionRule(object, metaclass=abc.ABCMeta): + """Garbage collection rule for column families within a table. + + Cells in the column family (within a table) fitting the rule will be + deleted during garbage collection. + + .. note:: + + This class is a do-nothing base class for all GC rules. + + .. note:: + + A string ``gc_expression`` can also be used with API requests, but + that value would be superceded by a ``gc_rule``. As a result, we + don't support that feature and instead support via native classes. + """ + + @abc.abstractmethod + def to_pb(self) -> table_pb2.GcRule: + raise NotImplementedError() + + +class DefaultGarbageCollectionRule(BaseGarbageCollectionRule): + """Default garbage collection rule. + + TODO: Add a sample for this. + """ + + def to_pb(self) -> table_pb2.GcRule: + return table_pb2.GcRule() + + +class MaxNumVersionsGarbageCollectionRule(BaseGarbageCollectionRule): + """Garbage collection limiting the number of versions of a cell. + + For example: + + .. literalinclude:: snippets_table.py + :start-after: [START bigtable_api_create_family_gc_max_versions] + :end-before: [END bigtable_api_create_family_gc_max_versions] + :dedent: 4 + + :type max_num_versions: int + :param max_num_versions: The maximum number of versions + """ + + def __init__(self, max_num_versions: int): + self.max_num_versions = max_num_versions + + def to_pb(self) -> table_pb2.GcRule: + """Converts the garbage collection rule to a protobuf. + + :rtype: :class:`.table_v2_pb2.GcRule` + :returns: The converted current object. + """ + return table_pb2.GcRule(max_num_versions=self.max_num_versions) + + +class MaxAgeGarbageCollectionRule(BaseGarbageCollectionRule): + """Garbage collection limiting the age of a cell. + + For example: + + .. literalinclude:: snippets_table.py + :start-after: [START bigtable_api_create_family_gc_max_age] + :end-before: [END bigtable_api_create_family_gc_max_age] + :dedent: 4 + + :type max_age: :class:`google.protobuf.duration_pb2.Duration` + :param max_age: The maximum age allowed for a cell in the table. + """ + + def __init__(self, max_age: duration_pb2.Duration): + self.max_age = max_age + + def to_pb(self) -> table_pb2.GcRule: + """Converts the garbage collection rule to a protobuf. + + :rtype: :class:`.table_v2_pb2.GcRule` + :returns: The converted current object. + """ + return table_pb2.GcRule(max_age=self.max_age) + + +class UnionGarbageCollectionRule(BaseGarbageCollectionRule): + """Union of garbage collection rules. + + For example: + + .. literalinclude:: snippets_table.py + :start-after: [START bigtable_api_create_family_gc_union] + :end-before: [END bigtable_api_create_family_gc_union] + :dedent: 4 + + :type rules: list + :param rules: List of :class:`GarbageCollectionRule`. + """ + + def __init__(self, rules): + self.rules = rules + + def to_pb(self) -> table_pb2.GcRule: + """Converts the union into a single GC rule as a protobuf. + + :rtype: :class:`.table_v2_pb2.GcRule` + :returns: The converted current object. + """ + union = table_pb2.GcRule.Union(rules=[rule.to_pb() for rule in self.rules]) + return table_pb2.GcRule(union=union) + + +class IntersectionGarbageCollectionRule(BaseGarbageCollectionRule): + """Intersection of garbage collection rules. + + For example: + + .. literalinclude:: snippets_table.py + :start-after: [START bigtable_api_create_family_gc_intersection] + :end-before: [END bigtable_api_create_family_gc_intersection] + :dedent: 4 + + :type rules: list + :param rules: List of :class:`GarbageCollectionRule`. + """ + + def __init__(self, rules): + self.rules = rules + + def to_pb(self) -> table_pb2.GcRule: + """Converts the intersection into a single GC rule as a protobuf. + + :rtype: :class:`.table_v2_pb2.GcRule` + :returns: The converted current object. + """ + intersection = table_pb2.GcRule.Intersection( + rules=[rule.to_pb() for rule in self.rules] + ) + return table_pb2.GcRule(intersection=intersection) diff --git a/google/cloud/bigtable/admin_v2/overlay/types/restore_table.py b/google/cloud/bigtable/admin_v2/overlay/types/restore_table.py new file mode 100644 index 000000000..41f87c2da --- /dev/null +++ b/google/cloud/bigtable/admin_v2/overlay/types/restore_table.py @@ -0,0 +1,64 @@ +# Copyright 2025 Google LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from google.api_core import operation +from google.protobuf import empty_pb2 + +from google.cloud.bigtable.admin_v2.types import OptimizeRestoredTableMetadata + +class RestoreTableOperation(operation.Operation): + def __init__(self, operations_client, restore_table_operation): + self._operations_client = operations_client + self._optimize_restore_table_operation = None + super().__init__( + restore_table_operation._operation, + restore_table_operation._refresh, + restore_table_operation._cancel, + restore_table_operation._result_type, + restore_table_operation._metadata_type, + polling=restore_table_operation._polling, + ) + + def optimize_restore_table_operation(self, + timeout=operation.Operation._DEFAULT_VALUE, + retry=None, + polling=None): + + self._blocking_poll(timeout=timeout, retry=retry, polling=polling) + + if self._exception is not None: + # pylint: disable=raising-bad-type + # Pylint doesn't recognize that this is valid in this case. + raise self._exception + + return self._optimize_restore_table_operation + + + def set_result(self, response): + optimize_restore_table_operation_name = self.metadata.optimize_table_operation_name + + # When the RestoreTable operation finishes, it might not necessarily trigger + # an optimize operation. + if optimize_restore_table_operation_name: + optimize_restore_table_operation = self._operations_client.get_operation( + name=optimize_restore_table_operation_name + ) + self._optimize_restore_table_operation = operation.from_gapic( + optimize_restore_table_operation, + self._operations_client, + empty_pb2.Empty, + metadata_type=OptimizeRestoredTableMetadata, + ) + + super().set_result(response) \ No newline at end of file From 30ac2f7cf2c6949a410f771feedb619b318a2604 Mon Sep 17 00:00:00 2001 From: Kevin Zheng Date: Wed, 30 Apr 2025 18:41:47 +0000 Subject: [PATCH 2/4] Added newlines --- google/cloud/bigtable/admin_v2/overlay/types/__init__.py | 2 +- google/cloud/bigtable/admin_v2/overlay/types/restore_table.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/google/cloud/bigtable/admin_v2/overlay/types/__init__.py b/google/cloud/bigtable/admin_v2/overlay/types/__init__.py index 456f80d24..d14854074 100644 --- a/google/cloud/bigtable/admin_v2/overlay/types/__init__.py +++ b/google/cloud/bigtable/admin_v2/overlay/types/__init__.py @@ -36,4 +36,4 @@ "IntersectionGarbageCollectionRule", "CheckConsistencyPollingFuture", "RestoreTableOperation", -) \ No newline at end of file +) diff --git a/google/cloud/bigtable/admin_v2/overlay/types/restore_table.py b/google/cloud/bigtable/admin_v2/overlay/types/restore_table.py index 41f87c2da..eda0af07f 100644 --- a/google/cloud/bigtable/admin_v2/overlay/types/restore_table.py +++ b/google/cloud/bigtable/admin_v2/overlay/types/restore_table.py @@ -61,4 +61,4 @@ def set_result(self, response): metadata_type=OptimizeRestoredTableMetadata, ) - super().set_result(response) \ No newline at end of file + super().set_result(response) From c853e164a6c02168e28e0a8b6c582da4614ad5d1 Mon Sep 17 00:00:00 2001 From: Kevin Zheng Date: Wed, 30 Apr 2025 19:51:34 +0000 Subject: [PATCH 3/4] linting --- .../bigtable/admin_v2/overlay/__init__.py | 2 +- .../services/bigtable_table_admin/__init__.py | 4 +--- .../services/bigtable_table_admin/client.py | 24 ++++++++++++------- .../admin_v2/overlay/types/consistency.py | 12 ++++++---- .../admin_v2/overlay/types/gc_rule.py | 2 +- .../admin_v2/overlay/types/restore_table.py | 14 +++++------ 6 files changed, 32 insertions(+), 26 deletions(-) diff --git a/google/cloud/bigtable/admin_v2/overlay/__init__.py b/google/cloud/bigtable/admin_v2/overlay/__init__.py index a26848416..e07c76d5e 100644 --- a/google/cloud/bigtable/admin_v2/overlay/__init__.py +++ b/google/cloud/bigtable/admin_v2/overlay/__init__.py @@ -34,5 +34,5 @@ "IntersectionGarbageCollectionRule", "RestoreTableOperation", "CheckConsistencyPollingFuture", - "BigtableTableAdminClient" + "BigtableTableAdminClient", ) diff --git a/google/cloud/bigtable/admin_v2/overlay/services/bigtable_table_admin/__init__.py b/google/cloud/bigtable/admin_v2/overlay/services/bigtable_table_admin/__init__.py index 6c7f49e21..ec9de1382 100644 --- a/google/cloud/bigtable/admin_v2/overlay/services/bigtable_table_admin/__init__.py +++ b/google/cloud/bigtable/admin_v2/overlay/services/bigtable_table_admin/__init__.py @@ -16,6 +16,4 @@ from .client import BigtableTableAdminClient -__all__ = ( - "BigtableTableAdminClient", -) +__all__ = ("BigtableTableAdminClient",) diff --git a/google/cloud/bigtable/admin_v2/overlay/services/bigtable_table_admin/client.py b/google/cloud/bigtable/admin_v2/overlay/services/bigtable_table_admin/client.py index 8344393b7..aaa668c61 100644 --- a/google/cloud/bigtable/admin_v2/overlay/services/bigtable_table_admin/client.py +++ b/google/cloud/bigtable/admin_v2/overlay/services/bigtable_table_admin/client.py @@ -41,11 +41,13 @@ from google.api_core import operation # type: ignore from google.cloud.bigtable.admin_v2.types import bigtable_table_admin -from google.cloud.bigtable.admin_v2.services.bigtable_table_admin import BaseBigtableTableAdminClient +from google.cloud.bigtable.admin_v2.services.bigtable_table_admin import ( + BaseBigtableTableAdminClient, +) from google.cloud.bigtable.admin_v2.overlay.types import consistency, restore_table -class BigtableTableAdminClient(BaseBigtableTableAdminClient): +class BigtableTableAdminClient(BaseBigtableTableAdminClient): def restore_table( self, request: Optional[Union[bigtable_table_admin.RestoreTableRequest, dict]] = None, @@ -130,7 +132,9 @@ def sample_restore_table(): metadata=metadata, ) - restore_table_operation = restore_table.RestoreTableOperation(self._transport.operations_client, operation) + restore_table_operation = restore_table.RestoreTableOperation( + self._transport.operations_client, operation + ) return restore_table_operation def await_consistency( @@ -145,7 +149,6 @@ def await_consistency( timeout: Union[float, object] = gapic_v1.method.DEFAULT, metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), ) -> consistency.CheckConsistencyPollingFuture: - api_call = functools.partial( self.check_consistency, request, @@ -167,7 +170,6 @@ def await_replication( timeout: Union[float, object] = gapic_v1.method.DEFAULT, metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), ) -> consistency.CheckConsistencyPollingFuture: - generate_consistency_response = self.generate_consistency_token( request, name=name, @@ -178,7 +180,7 @@ def await_replication( # Create the CheckConsistencyRequest object. check_consistency_request = bigtable_table_admin.CheckConsistencyRequest() - + # If the generate_consistency_token request is valid, there's a name in the request object # or the name parameter. if isinstance(request, dict): @@ -188,6 +190,10 @@ def await_replication( else: check_consistency_request.name = name - check_consistency_request.consistency_token = generate_consistency_response.consistency_token - - return self.await_consistency(check_consistency_request, retry=retry, timeout=timeout, metadata=metadata) + check_consistency_request.consistency_token = ( + generate_consistency_response.consistency_token + ) + + return self.await_consistency( + check_consistency_request, retry=retry, timeout=timeout, metadata=metadata + ) diff --git a/google/cloud/bigtable/admin_v2/overlay/types/consistency.py b/google/cloud/bigtable/admin_v2/overlay/types/consistency.py index 40e5e7591..1038cad7b 100644 --- a/google/cloud/bigtable/admin_v2/overlay/types/consistency.py +++ b/google/cloud/bigtable/admin_v2/overlay/types/consistency.py @@ -25,11 +25,13 @@ class CheckConsistencyPollingFuture(polling.PollingFuture): - def __init__(self, + def __init__( + self, check_consistency_call: Callable, default_retry: OptionalRetry = gapic_v1.method.DEFAULT, polling: retries.Retry = polling.DEFAULT_POLLING, - **kwargs): + **kwargs + ): super(CheckConsistencyPollingFuture, self).__init__(polling=polling, **kwargs) # Done is called with two different scenarios, retry is specified or not specified. @@ -37,8 +39,8 @@ def __init__(self, # that. self._check_consistency_call = check_consistency_call self._default_retry = default_retry - - def done(self, retry: OptionalRetry=None): + + def done(self, retry: OptionalRetry = None): if self._result_set: return True @@ -55,6 +57,6 @@ def done(self, retry: OptionalRetry=None): def cancel(self): raise NotImplementedError("Cannot cancel consistency token operation") - + def cancelled(self): raise NotImplementedError("Cannot cancel consistency token operation") diff --git a/google/cloud/bigtable/admin_v2/overlay/types/gc_rule.py b/google/cloud/bigtable/admin_v2/overlay/types/gc_rule.py index 9da092197..4a4dd5775 100644 --- a/google/cloud/bigtable/admin_v2/overlay/types/gc_rule.py +++ b/google/cloud/bigtable/admin_v2/overlay/types/gc_rule.py @@ -36,7 +36,7 @@ class BaseGarbageCollectionRule(object, metaclass=abc.ABCMeta): that value would be superceded by a ``gc_rule``. As a result, we don't support that feature and instead support via native classes. """ - + @abc.abstractmethod def to_pb(self) -> table_pb2.GcRule: raise NotImplementedError() diff --git a/google/cloud/bigtable/admin_v2/overlay/types/restore_table.py b/google/cloud/bigtable/admin_v2/overlay/types/restore_table.py index eda0af07f..943cb617e 100644 --- a/google/cloud/bigtable/admin_v2/overlay/types/restore_table.py +++ b/google/cloud/bigtable/admin_v2/overlay/types/restore_table.py @@ -17,6 +17,7 @@ from google.cloud.bigtable.admin_v2.types import OptimizeRestoredTableMetadata + class RestoreTableOperation(operation.Operation): def __init__(self, operations_client, restore_table_operation): self._operations_client = operations_client @@ -30,11 +31,9 @@ def __init__(self, operations_client, restore_table_operation): polling=restore_table_operation._polling, ) - def optimize_restore_table_operation(self, - timeout=operation.Operation._DEFAULT_VALUE, - retry=None, - polling=None): - + def optimize_restore_table_operation( + self, timeout=operation.Operation._DEFAULT_VALUE, retry=None, polling=None + ): self._blocking_poll(timeout=timeout, retry=retry, polling=polling) if self._exception is not None: @@ -44,9 +43,10 @@ def optimize_restore_table_operation(self, return self._optimize_restore_table_operation - def set_result(self, response): - optimize_restore_table_operation_name = self.metadata.optimize_table_operation_name + optimize_restore_table_operation_name = ( + self.metadata.optimize_table_operation_name + ) # When the RestoreTable operation finishes, it might not necessarily trigger # an optimize operation. From fe1c6edd9bf42ef55be8b9bac8d908f6d7e9afbb Mon Sep 17 00:00:00 2001 From: Kevin Zheng Date: Fri, 16 May 2025 15:00:44 +0000 Subject: [PATCH 4/4] Added docstrings for restore table and consistency token polling; removed gc_rule --- .../bigtable/admin_v2/overlay/__init__.py | 27 +-- .../services/bigtable_table_admin/client.py | 164 ++++++++++++++++-- .../admin_v2/overlay/types/__init__.py | 13 -- .../admin_v2/overlay/types/consistency.py | 37 +++- .../admin_v2/overlay/types/gc_rule.py | 160 ----------------- .../admin_v2/overlay/types/restore_table.py | 41 ++++- 6 files changed, 244 insertions(+), 198 deletions(-) delete mode 100644 google/cloud/bigtable/admin_v2/overlay/types/gc_rule.py diff --git a/google/cloud/bigtable/admin_v2/overlay/__init__.py b/google/cloud/bigtable/admin_v2/overlay/__init__.py index e07c76d5e..3b85e4989 100644 --- a/google/cloud/bigtable/admin_v2/overlay/__init__.py +++ b/google/cloud/bigtable/admin_v2/overlay/__init__.py @@ -11,13 +11,25 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# +# This directory and all its subdirectories are the only handwritten +# components of the otherwise autogenerated google/cloud/bigtable/admin_v2. +# The purpose of the overlay directory is to add additional functionality to +# the autogenerated library while preserving its developer experience. These +# handwritten additions currently consist of the following: +# +# 1. TODO: Document final GcRule design choice here +# 2. An LRO class for restore_table that exposes an Operation for +# OptimizeRestoreTable, if that LRO exists. +# 3. New methods (wait_for_consistency and wait_for_replication) that return +# a polling future class for automatically polling check_consistency. +# +# This directory is structured to mirror that of a typical autogenerated library (e.g. +# services/types subdirectories), and the aforementioned handwritten additions are +# currently implemented as either types under overlay/types or in methods in an overwritten +# client class under overlay/services. from .types import ( - BaseGarbageCollectionRule, - MaxAgeGarbageCollectionRule, - MaxNumVersionsGarbageCollectionRule, - UnionGarbageCollectionRule, - IntersectionGarbageCollectionRule, RestoreTableOperation, CheckConsistencyPollingFuture, ) @@ -27,11 +39,6 @@ ) __all__ = ( - "BaseGarbageCollectionRule", - "MaxAgeGarbageCollectionRule", - "MaxNumVersionsGarbageCollectionRule", - "UnionGarbageCollectionRule", - "IntersectionGarbageCollectionRule", "RestoreTableOperation", "CheckConsistencyPollingFuture", "BigtableTableAdminClient", diff --git a/google/cloud/bigtable/admin_v2/overlay/services/bigtable_table_admin/client.py b/google/cloud/bigtable/admin_v2/overlay/services/bigtable_table_admin/client.py index aaa668c61..e7ee4db3a 100644 --- a/google/cloud/bigtable/admin_v2/overlay/services/bigtable_table_admin/client.py +++ b/google/cloud/bigtable/admin_v2/overlay/services/bigtable_table_admin/client.py @@ -26,7 +26,8 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -# + + import functools from typing import Optional, Sequence, Tuple, Union @@ -57,18 +58,23 @@ def restore_table( metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), ) -> restore_table.RestoreTableOperation: r"""Create a new table by restoring from a completed backup. The - returned table [long-running - operation][google.longrunning.Operation] can be used to track - the progress of the operation, and to cancel it. The - [metadata][google.longrunning.Operation.metadata] field type is - [RestoreTableMetadata][google.bigtable.admin.v2.RestoreTableMetadata]. - The [response][google.longrunning.Operation.response] type is - [Table][google.bigtable.admin.v2.Table], if successful. + returned table :ref:`long-running operation + <:class:google.cloud.bigtable.admin_v2.overlay.types.restore_table.RestoreTableOperation>` + can be used to track the progress of the operation, and to cancel it. The + :ref:`metadata <:attr:google.api_core.operation.Operation.metadata>` field type is + :ref:`RestoreTableMetadata <:class:google.bigtable.admin_v2.types.RestoreTableMetadata>`. + The :ref:`response <:meth:google.api_core.operation.Operation.result>` type is + :class:`google.cloud.bigtable.admin_v2.types.Table`, if successful. + + Additionally, the returned :ref:`long-running-operation <:class:google.cloud.bigtable.admin_v2.overlay.types.restore_table.RestoreTableOperation>` + provides a method, :meth:`google.cloud.bigtable.admin_v2.overlay.types.restore_table.RestoreTableOperation.optimize_restore_table_operation` that + provides access to a :class:`google.api_core.operation.Operation` object representing the OptimizeRestoreTable long-running-operation + after the current one has completed. .. code-block:: python - # This snippet has been automatically generated and should be regarded as a - # code template only. + # This snippet should be regarded as a code template only. + # # It will require modifications to work: # - It may require correct/in-range values for request initialization. # - It may require specifying regional endpoints when creating the service @@ -137,7 +143,7 @@ def sample_restore_table(): ) return restore_table_operation - def await_consistency( + def wait_for_consistency( self, request: Optional[ Union[bigtable_table_admin.CheckConsistencyRequest, dict] @@ -149,6 +155,77 @@ def await_consistency( timeout: Union[float, object] = gapic_v1.method.DEFAULT, metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), ) -> consistency.CheckConsistencyPollingFuture: + r"""Creates a polling future that periodically checks replication + consistency based on a consistency token, that is, if replication + has caught up based on the conditions specified in the token and + the check request. The future will stop checking once the underlying + :meth:`check_consistency` request involving that token returns True. + + .. code-block:: python + + # This snippet should be regarded as a code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud.bigtable import admin_v2 + + def sample_wait_for_consistency(): + # Create a client + client = admin_v2.BigtableTableAdminClient() + + # Initialize request argument(s) + request = admin_v2.CheckConsistencyRequest( + name="name_value", + consistency_token="consistency_token_value", + ) + + # Make the request + future = client.wait_for_consistency(request=request) + + # Wait for the table to become consistent + print("Waiting for operation to complete...") + + response = future.result() + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.bigtable.admin_v2.types.CheckConsistencyRequest, dict]): + The request object. Request message for + [google.bigtable.admin.v2.BigtableTableAdmin.CheckConsistency][google.bigtable.admin.v2.BigtableTableAdmin.CheckConsistency] + name (str): + Required. The unique name of the Table for which to + check replication consistency. Values are of the form + ``projects/{project}/instances/{instance}/tables/{table}``. + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + consistency_token (str): + Required. The token created using + GenerateConsistencyToken for the Table. + + This corresponds to the ``consistency_token`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.cloud.bigtable.admin_v2.overlay.types.CheckConsistencyPollingFuture: + An object representing a polling future. + + The result type for the operation will be `bool`, and will return True when the + consistency check involving the given consistency token returns True. + """ api_call = functools.partial( self.check_consistency, request, @@ -159,7 +236,7 @@ def await_consistency( ) return consistency.CheckConsistencyPollingFuture(api_call, default_retry=retry) - def await_replication( + def wait_for_replication( self, request: Optional[ Union[bigtable_table_admin.GenerateConsistencyTokenRequest, dict] @@ -170,6 +247,69 @@ def await_replication( timeout: Union[float, object] = gapic_v1.method.DEFAULT, metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), ) -> consistency.CheckConsistencyPollingFuture: + r"""Generates a consistency token for a Table, which will then + be used to create a polling future for checking the replication + consistency based on that token. The future will stop checking + once the underlying :meth:`check_consistency` request involving + that token returns True. + + .. code-block:: python + + # This snippet should be regarded as a code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud.bigtable import admin_v2 + + def sample_wait_for_replication(): + # Create a client + client = admin_v2.BigtableTableAdminClient() + + # Initialize request argument(s) + request = admin_v2.GenerateConsistencyTokenRequest( + name="name_value", + ) + + # Make the request + future = client.wait_for_replication(request=request) + + # Wait for the table to become consistent + print("Waiting for operation to complete...") + + response = future.result() + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.bigtable.admin_v2.types.GenerateConsistencyTokenRequest, dict]): + The request object. Request message for + [google.bigtable.admin.v2.BigtableTableAdmin.GenerateConsistencyToken][google.bigtable.admin.v2.BigtableTableAdmin.GenerateConsistencyToken] + name (str): + Required. The unique name of the Table for which to + create a consistency token. Values are of the form + ``projects/{project}/instances/{instance}/tables/{table}``. + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.cloud.bigtable.admin_v2.overlay.types.CheckConsistencyPollingFuture: + An object representing a polling future. + + The result type for the operation will be `bool`, and will return True when the + consistency check involving the given consistency token returns True. + """ generate_consistency_response = self.generate_consistency_token( request, name=name, diff --git a/google/cloud/bigtable/admin_v2/overlay/types/__init__.py b/google/cloud/bigtable/admin_v2/overlay/types/__init__.py index d14854074..01b1f7115 100644 --- a/google/cloud/bigtable/admin_v2/overlay/types/__init__.py +++ b/google/cloud/bigtable/admin_v2/overlay/types/__init__.py @@ -12,14 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -from .gc_rule import ( - BaseGarbageCollectionRule, - MaxAgeGarbageCollectionRule, - MaxNumVersionsGarbageCollectionRule, - UnionGarbageCollectionRule, - IntersectionGarbageCollectionRule, -) - from .consistency import ( CheckConsistencyPollingFuture, ) @@ -29,11 +21,6 @@ ) __all__ = ( - "BaseGarbageCollectionRule", - "MaxAgeGarbageCollectionRule", - "MaxNumVersionsGarbageCollectionRule", - "UnionGarbageCollectionRule", - "IntersectionGarbageCollectionRule", "CheckConsistencyPollingFuture", "RestoreTableOperation", ) diff --git a/google/cloud/bigtable/admin_v2/overlay/types/consistency.py b/google/cloud/bigtable/admin_v2/overlay/types/consistency.py index 1038cad7b..f5775b697 100644 --- a/google/cloud/bigtable/admin_v2/overlay/types/consistency.py +++ b/google/cloud/bigtable/admin_v2/overlay/types/consistency.py @@ -17,6 +17,7 @@ from google.api_core.future import polling from google.api_core import gapic_v1 from google.api_core import retry as retries +from google.bigtable.admin_v2.types import bigtable_table_admin try: OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] @@ -25,9 +26,29 @@ class CheckConsistencyPollingFuture(polling.PollingFuture): + """A Future that polls an underlying `check_consistency` operation until it returns True. + + **This class should not be instantiated by users** and should only be instantiated by the admin + client's `google.cloud.bigtable.admin_v2.overlay.services.BigtableTableAdminClient.wait_for_consistency` or + :meth:`google.cloud.bigtable.admin_v2.overlay.services.BigtableTableAdminClient.wait_for_replication` methods. + + Args: + check_consistency_call(Callable[ + [Optional[google.api_core.retry.Retry], + google.cloud.bigtable.admin_v2.types.CheckConsistencyResponse]): + A :meth:`google.cloud.bigtable.admin_v2.overlay.services.BigtableTableAdminClient.check_consistency` call + from :class:`google.cloud.bigtable.admin_v2.overlay.services.BigtableTableAdminClient`. The call should fix + every user parameter except for retry, which will be done via :meth:`functools.partial`. + default_retry(Optional[google.api_core.retry.Retry]): The `retry` parameter passed in to either `wait_for_consistency` + or `wait_for_replication`. + polling (google.api_core.retry.Retry): The configuration used for polling. + This parameter controls how often :meth:`done` is polled. If the + ``timeout`` argument is specified in :meth:`result` method it will + override the ``polling.timeout`` property. + """ def __init__( self, - check_consistency_call: Callable, + check_consistency_call: Callable[[OptionalRetry], bigtable_table_admin.CheckConsistencyResponse], default_retry: OptionalRetry = gapic_v1.method.DEFAULT, polling: retries.Retry = polling.DEFAULT_POLLING, **kwargs @@ -41,6 +62,20 @@ def __init__( self._default_retry = default_retry def done(self, retry: OptionalRetry = None): + """Checks to see if the operation is complete. + + This will be return True when the underlying check_consistency call returns + True while polling. + + Args: + retry (google.api_core.retry.Retry): (Optional) How to retry the + polling RPC (to not be confused with polling configuration. See + the documentation for :meth:`result` for details). + + Returns: + bool: True if the operation is complete, False otherwise. + """ + if self._result_set: return True diff --git a/google/cloud/bigtable/admin_v2/overlay/types/gc_rule.py b/google/cloud/bigtable/admin_v2/overlay/types/gc_rule.py deleted file mode 100644 index 4a4dd5775..000000000 --- a/google/cloud/bigtable/admin_v2/overlay/types/gc_rule.py +++ /dev/null @@ -1,160 +0,0 @@ -# Copyright 2025 Google LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# TODO: Samples in docstrings will be slightly off. Fix this later. Also improve docstrings. - -import abc - -from google.protobuf import duration_pb2 -from google.cloud.bigtable.admin_v2.types import table as table_pb2 - - -class BaseGarbageCollectionRule(object, metaclass=abc.ABCMeta): - """Garbage collection rule for column families within a table. - - Cells in the column family (within a table) fitting the rule will be - deleted during garbage collection. - - .. note:: - - This class is a do-nothing base class for all GC rules. - - .. note:: - - A string ``gc_expression`` can also be used with API requests, but - that value would be superceded by a ``gc_rule``. As a result, we - don't support that feature and instead support via native classes. - """ - - @abc.abstractmethod - def to_pb(self) -> table_pb2.GcRule: - raise NotImplementedError() - - -class DefaultGarbageCollectionRule(BaseGarbageCollectionRule): - """Default garbage collection rule. - - TODO: Add a sample for this. - """ - - def to_pb(self) -> table_pb2.GcRule: - return table_pb2.GcRule() - - -class MaxNumVersionsGarbageCollectionRule(BaseGarbageCollectionRule): - """Garbage collection limiting the number of versions of a cell. - - For example: - - .. literalinclude:: snippets_table.py - :start-after: [START bigtable_api_create_family_gc_max_versions] - :end-before: [END bigtable_api_create_family_gc_max_versions] - :dedent: 4 - - :type max_num_versions: int - :param max_num_versions: The maximum number of versions - """ - - def __init__(self, max_num_versions: int): - self.max_num_versions = max_num_versions - - def to_pb(self) -> table_pb2.GcRule: - """Converts the garbage collection rule to a protobuf. - - :rtype: :class:`.table_v2_pb2.GcRule` - :returns: The converted current object. - """ - return table_pb2.GcRule(max_num_versions=self.max_num_versions) - - -class MaxAgeGarbageCollectionRule(BaseGarbageCollectionRule): - """Garbage collection limiting the age of a cell. - - For example: - - .. literalinclude:: snippets_table.py - :start-after: [START bigtable_api_create_family_gc_max_age] - :end-before: [END bigtable_api_create_family_gc_max_age] - :dedent: 4 - - :type max_age: :class:`google.protobuf.duration_pb2.Duration` - :param max_age: The maximum age allowed for a cell in the table. - """ - - def __init__(self, max_age: duration_pb2.Duration): - self.max_age = max_age - - def to_pb(self) -> table_pb2.GcRule: - """Converts the garbage collection rule to a protobuf. - - :rtype: :class:`.table_v2_pb2.GcRule` - :returns: The converted current object. - """ - return table_pb2.GcRule(max_age=self.max_age) - - -class UnionGarbageCollectionRule(BaseGarbageCollectionRule): - """Union of garbage collection rules. - - For example: - - .. literalinclude:: snippets_table.py - :start-after: [START bigtable_api_create_family_gc_union] - :end-before: [END bigtable_api_create_family_gc_union] - :dedent: 4 - - :type rules: list - :param rules: List of :class:`GarbageCollectionRule`. - """ - - def __init__(self, rules): - self.rules = rules - - def to_pb(self) -> table_pb2.GcRule: - """Converts the union into a single GC rule as a protobuf. - - :rtype: :class:`.table_v2_pb2.GcRule` - :returns: The converted current object. - """ - union = table_pb2.GcRule.Union(rules=[rule.to_pb() for rule in self.rules]) - return table_pb2.GcRule(union=union) - - -class IntersectionGarbageCollectionRule(BaseGarbageCollectionRule): - """Intersection of garbage collection rules. - - For example: - - .. literalinclude:: snippets_table.py - :start-after: [START bigtable_api_create_family_gc_intersection] - :end-before: [END bigtable_api_create_family_gc_intersection] - :dedent: 4 - - :type rules: list - :param rules: List of :class:`GarbageCollectionRule`. - """ - - def __init__(self, rules): - self.rules = rules - - def to_pb(self) -> table_pb2.GcRule: - """Converts the intersection into a single GC rule as a protobuf. - - :rtype: :class:`.table_v2_pb2.GcRule` - :returns: The converted current object. - """ - intersection = table_pb2.GcRule.Intersection( - rules=[rule.to_pb() for rule in self.rules] - ) - return table_pb2.GcRule(intersection=intersection) diff --git a/google/cloud/bigtable/admin_v2/overlay/types/restore_table.py b/google/cloud/bigtable/admin_v2/overlay/types/restore_table.py index 943cb617e..495fbdf3a 100644 --- a/google/cloud/bigtable/admin_v2/overlay/types/restore_table.py +++ b/google/cloud/bigtable/admin_v2/overlay/types/restore_table.py @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +from typing import Optional + from google.api_core import operation from google.protobuf import empty_pb2 @@ -19,7 +21,24 @@ class RestoreTableOperation(operation.Operation): - def __init__(self, operations_client, restore_table_operation): + """A Future for interacting with Bigtable Admin's RestoreTable Long-Running Operation. + + This is needed to expose a potential long-running operation that might run after this operation + finishes, OptimizeRestoreTable. This is exposed via the the :meth:`optimize_restore_table` method. + + **This class should not be instantiated by users** and should only be instantiated by the admin + client's `google.cloud.bigtable.admin_v2.overlay.services.BigtableTableAdminClient.restore_table` + method. + + Args: + operations_client (google.api_core.operations_v1.AbstractOperationsClient): The operations + client from the :class:`google.cloud.bigtable.admin_v2.overlay.services.BigtableTableAdminClient`'s + transport. + restore_table_operation (google.api_core.operation.Operation): A :class:`google.api_core.operation.Operation` + instance resembling a RestoreTable long-running operation + """ + + def __init__(self, operations_client, restore_table_operation: operation.Operation): self._operations_client = operations_client self._optimize_restore_table_operation = None super().__init__( @@ -33,7 +52,25 @@ def __init__(self, operations_client, restore_table_operation): def optimize_restore_table_operation( self, timeout=operation.Operation._DEFAULT_VALUE, retry=None, polling=None - ): + ) -> Optional[operation.Operation]: + """Gets the OptimizeRestoreTable long-running operation that runs after this operation finishes. + + This is a blocking call that will return the operation after this current long-running operation + finishes, just like :meth:`result`. The follow-up operation has + :ref:`metadata <:attr:google.api_core.operation.Operation.metadata>` type + :ref:`OptimizeRestoreTableMetadata <:class:google.bigtable.admin_v2.types.OptimizeRestoreTableMetadata>` + and no return value, but can be waited for with `result`. + + The current operation might not trigger a follow-up OptimizeRestoreTable operation, in which case, this + method will return `None`. + + For more documentation on the parameters for this method, see the documentation on :meth:`result`. + + Returns: + Optional[google.api_core.operation.Operation]: + An object representing a long-running operation, or None if there is no OptimizeRestoreTable operation + after this one. + """ self._blocking_poll(timeout=timeout, retry=retry, polling=polling) if self._exception is not None: