Skip to content

Commit 5ea9f0e

Browse files
Merge branch 'main' into csm_1_data_model
2 parents 4a4f80a + 451fd97 commit 5ea9f0e

File tree

210 files changed

+27911
-1579
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

210 files changed

+27911
-1579
lines changed

.release-please-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
".": "2.31.0"
2+
".": "2.32.0"
33
}

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@
44

55
[1]: https://pypi.org/project/google-cloud-bigtable/#history
66

7+
## [2.32.0](https://github.com/googleapis/python-bigtable/compare/v2.31.0...v2.32.0) (2025-08-01)
8+
9+
10+
### Features
11+
12+
* Add Idempotency to Cloud Bigtable MutateRowsRequest API ([#1143](https://github.com/googleapis/python-bigtable/issues/1143)) ([c3e3eb0](https://github.com/googleapis/python-bigtable/commit/c3e3eb0e4ce44ece72b150dc5822846627074fba))
13+
* Add support for AddToCell in Data Client ([#1147](https://github.com/googleapis/python-bigtable/issues/1147)) ([1a5b4b5](https://github.com/googleapis/python-bigtable/commit/1a5b4b514cadae5c83d61296314285d3774992c5))
14+
* Implement SQL support in test proxy ([#1106](https://github.com/googleapis/python-bigtable/issues/1106)) ([7a91bbf](https://github.com/googleapis/python-bigtable/commit/7a91bbfb9df23f7e93c40b88648840342af6f16f))
15+
* Modernized Bigtable Admin Client featuring selective GAPIC generation ([#1177](https://github.com/googleapis/python-bigtable/issues/1177)) ([58e7d37](https://github.com/googleapis/python-bigtable/commit/58e7d3782df6b13a42af053263afc575222a6b83))
16+
717
## [2.31.0](https://github.com/googleapis/python-bigtable/compare/v2.30.1...v2.31.0) (2025-05-22)
818

919

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
Admin Client
2+
============
3+
.. toctree::
4+
:maxdepth: 2
5+
6+
services_
7+
types_
8+
9+
..
10+
This should be the only handwritten RST file in this directory.
11+
Everything else should be autogenerated.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
BigtableInstanceAdmin
2+
---------------------------------------
3+
4+
.. automodule:: google.cloud.bigtable_admin_v2.services.bigtable_instance_admin
5+
:members:
6+
:inherited-members:
7+
8+
.. automodule:: google.cloud.bigtable_admin_v2.services.bigtable_instance_admin.pagers
9+
:members:
10+
:inherited-members:
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
BigtableTableAdmin
2+
------------------------------------
3+
4+
.. automodule:: google.cloud.bigtable_admin_v2.overlay.services.bigtable_table_admin
5+
:members:
6+
:inherited-members:
7+
8+
.. automodule:: google.cloud.bigtable_admin_v2.services.bigtable_table_admin.pagers
9+
:members:
10+
:inherited-members:

docs/admin_client/services_.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Services for Google Cloud Bigtable Admin v2 API
2+
===============================================
3+
.. toctree::
4+
:maxdepth: 2
5+
6+
bigtable_instance_admin
7+
bigtable_table_admin

docs/admin_client/types_.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Types for Google Cloud Bigtable Admin v2 API
2+
============================================
3+
4+
.. automodule:: google.cloud.bigtable_admin_v2.types
5+
:members:
6+
:show-inheritance:
7+
8+
.. automodule:: google.cloud.bigtable_admin_v2.overlay.types
9+
:members:
10+
:show-inheritance:

docs/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Client Types
99

1010
data_client/data_client_usage
1111
classic_client/usage
12-
12+
admin_client/admin_client_usage
1313

1414
Changelog
1515
---------

docs/scripts/patch_devsite_toc.py

Lines changed: 86 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"""
2121

2222

23+
import glob
2324
import yaml
2425
import os
2526
import shutil
@@ -153,6 +154,81 @@ def copy_markdown(self):
153154
f"_build/html/docfx_yaml",
154155
)
155156

157+
def validate_section(self, toc):
158+
# Make sure each rst file is listed in the toc.
159+
items_in_toc = [
160+
d["items"] for d in toc[0]["items"] if d["name"] == self.title and ".rst"
161+
][0]
162+
items_in_dir = [f for f in os.listdir(self.dir_name) if f.endswith(".rst")]
163+
# subtract 1 for index
164+
assert len(items_in_toc) == len(items_in_dir) - 1
165+
for file in items_in_dir:
166+
if file != self.index_file_name:
167+
base_name, _ = os.path.splitext(file)
168+
assert any(d["href"] == f"{base_name}.md" for d in items_in_toc)
169+
# make sure the markdown files are present in the docfx_yaml directory
170+
md_files = [d["href"] for d in items_in_toc]
171+
for file in md_files:
172+
assert os.path.exists(f"_build/html/docfx_yaml/{file}")
173+
174+
175+
class UIDFilteredTocSection(TocSection):
176+
def __init__(self, toc_file_path, section_name, title, uid_prefix):
177+
"""Creates a filtered section denoted by section_name in the toc_file_path to items with the given UID prefix.
178+
179+
The section is then renamed to the title.
180+
"""
181+
current_toc = yaml.safe_load(open(toc_file_path, "r"))
182+
self.uid_prefix = uid_prefix
183+
184+
# Since we are looking for a specific section_name there should only
185+
# be one match.
186+
section_items = [
187+
d for d in current_toc[0]["items"] if d["name"] == section_name
188+
][0]["items"]
189+
filtered_items = [d for d in section_items if d["uid"].startswith(uid_prefix)]
190+
self.items = filtered_items
191+
self.title = title
192+
193+
def copy_markdown(self):
194+
"""
195+
No-op because we are filtering on UIDs, not markdown files.
196+
"""
197+
pass
198+
199+
def validate_section(self, toc):
200+
uids_in_toc = set()
201+
202+
# A UID-filtered TOC tree looks like the following:
203+
# - items:
204+
# <optional> items: <more stuff>
205+
# name: <name>
206+
# uid: <fully qualified path to a class>
207+
#
208+
# Walk through the TOC tree to find all UIDs recursively.
209+
def find_uids_in_items(items):
210+
uids_in_toc.add(items["uid"])
211+
for subitem in items.get("items", []):
212+
find_uids_in_items(subitem)
213+
214+
items_in_toc = [d["items"] for d in toc[0]["items"] if d["name"] == self.title][
215+
0
216+
]
217+
for item in items_in_toc:
218+
find_uids_in_items(item)
219+
220+
# Now that we have all the UIDs, first match all of them
221+
# with corresponding .yml files.
222+
for uid in uids_in_toc:
223+
assert os.path.exists(f"_build/html/docfx_yaml/{uid}.yml")
224+
225+
# Also validate that every uid yml file that starts with the uid_prefix
226+
# exists in the section.
227+
for filename in glob.glob(
228+
f"{self.uid_prefix}*.yml", root_dir="_build/html/docfx_yaml"
229+
):
230+
assert filename[:-4] in uids_in_toc
231+
156232

157233
def validate_toc(toc_file_path, expected_section_list, added_sections):
158234
current_toc = yaml.safe_load(open(toc_file_path, "r"))
@@ -164,43 +240,27 @@ def validate_toc(toc_file_path, expected_section_list, added_sections):
164240
# make sure each customs ection is in the toc
165241
for section in added_sections:
166242
assert section.title in found_sections
167-
# make sure each rst file in each custom section dir is listed in the toc
168-
for section in added_sections:
169-
items_in_toc = [
170-
d["items"]
171-
for d in current_toc[0]["items"]
172-
if d["name"] == section.title and ".rst"
173-
][0]
174-
items_in_dir = [f for f in os.listdir(section.dir_name) if f.endswith(".rst")]
175-
# subtract 1 for index
176-
assert len(items_in_toc) == len(items_in_dir) - 1
177-
for file in items_in_dir:
178-
if file != section.index_file_name:
179-
base_name, _ = os.path.splitext(file)
180-
assert any(d["href"] == f"{base_name}.md" for d in items_in_toc)
181-
# make sure the markdown files are present in the docfx_yaml directory
182-
for section in added_sections:
183-
items_in_toc = [
184-
d["items"]
185-
for d in current_toc[0]["items"]
186-
if d["name"] == section.title and ".rst"
187-
][0]
188-
md_files = [d["href"] for d in items_in_toc]
189-
for file in md_files:
190-
assert os.path.exists(f"_build/html/docfx_yaml/{file}")
243+
section.validate_section(current_toc)
191244
print("Toc validation passed")
192245

193246

194247
if __name__ == "__main__":
195248
# Add secrtions for the async_data_client and classic_client directories
196249
toc_path = "_build/html/docfx_yaml/toc.yml"
250+
197251
custom_sections = [
198252
TocSection(dir_name="data_client", index_file_name="data_client_usage.rst"),
253+
UIDFilteredTocSection(
254+
toc_file_path=toc_path,
255+
section_name="Bigtable Admin V2",
256+
title="Admin Client",
257+
uid_prefix="google.cloud.bigtable_admin_v2",
258+
),
199259
TocSection(dir_name="classic_client", index_file_name="usage.rst"),
200260
]
201261
add_sections(toc_path, custom_sections)
202262
# Remove the Bigtable section, since it has duplicated data
203-
remove_sections(toc_path, ["Bigtable"])
263+
remove_sections(toc_path, ["Bigtable", "Bigtable Admin V2"])
204264
# run validation to make sure yaml is structured as we expect
205265
validate_toc(
206266
toc_file_path=toc_path,
@@ -210,6 +270,7 @@ def validate_toc(toc_file_path, expected_section_list, added_sections):
210270
"Changelog",
211271
"Multiprocessing",
212272
"Data Client",
273+
"Admin Client",
213274
"Classic Client",
214275
],
215276
added_sections=custom_sections,

google/cloud/bigtable/backup.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import re
1818

1919
from google.cloud._helpers import _datetime_to_pb_timestamp # type: ignore
20-
from google.cloud.bigtable_admin_v2 import BigtableTableAdminClient
20+
from google.cloud.bigtable_admin_v2 import BaseBigtableTableAdminClient
2121
from google.cloud.bigtable_admin_v2.types import table
2222
from google.cloud.bigtable.encryption_info import EncryptionInfo
2323
from google.cloud.bigtable.policy import Policy
@@ -106,7 +106,7 @@ def name(self):
106106
if not self._cluster:
107107
raise ValueError('"cluster" parameter must be set')
108108

109-
return BigtableTableAdminClient.backup_path(
109+
return BaseBigtableTableAdminClient.backup_path(
110110
project=self._instance._client.project,
111111
instance=self._instance.instance_id,
112112
cluster=self._cluster,
@@ -141,7 +141,7 @@ def parent(self):
141141
:returns: A full path to the parent cluster.
142142
"""
143143
if not self._parent and self._cluster:
144-
self._parent = BigtableTableAdminClient.cluster_path(
144+
self._parent = BaseBigtableTableAdminClient.cluster_path(
145145
project=self._instance._client.project,
146146
instance=self._instance.instance_id,
147147
cluster=self._cluster,
@@ -163,7 +163,7 @@ def source_table(self):
163163
:returns: The Table name.
164164
"""
165165
if not self._source_table and self.table_id:
166-
self._source_table = BigtableTableAdminClient.table_path(
166+
self._source_table = BaseBigtableTableAdminClient.table_path(
167167
project=self._instance._client.project,
168168
instance=self._instance.instance_id,
169169
table=self.table_id,
@@ -226,7 +226,7 @@ def size_bytes(self):
226226
def state(self):
227227
"""The current state of this Backup.
228228
229-
:rtype: :class:`~google.cloud.bigtable_admin_v2.gapic.enums.Backup.State`
229+
:rtype: :class:`~google.cloud.bigtable_admin_v2.types.table.Backup.State`
230230
:returns: The current state of this Backup.
231231
"""
232232
return self._state
@@ -305,8 +305,7 @@ def create(self, cluster_id=None):
305305
created Backup.
306306
307307
:rtype: :class:`~google.api_core.operation.Operation`
308-
:returns: :class:`~google.cloud.bigtable_admin_v2.types._OperationFuture`
309-
instance, to be used to poll the status of the 'create' request
308+
:returns: A future to be used to poll the status of the 'create' request
310309
:raises Conflict: if the Backup already exists
311310
:raises NotFound: if the Instance owning the Backup does not exist
312311
:raises BadRequest: if the `table` or `expire_time` values are invalid,
@@ -412,7 +411,7 @@ def restore(self, table_id, instance_id=None):
412411
:param instance_id: (Optional) The ID of the Instance to restore the
413412
backup into, if different from the current one.
414413
415-
:rtype: :class:`~google.cloud.bigtable_admin_v2.types._OperationFuture`
414+
:rtype: :class:`~google.api_core.operation.Operation`
416415
:returns: A future to be used to poll the status of the 'restore'
417416
request.
418417
@@ -426,14 +425,14 @@ def restore(self, table_id, instance_id=None):
426425
"""
427426
api = self._instance._client.table_admin_client
428427
if instance_id:
429-
parent = BigtableTableAdminClient.instance_path(
428+
parent = BaseBigtableTableAdminClient.instance_path(
430429
project=self._instance._client.project,
431430
instance=instance_id,
432431
)
433432
else:
434433
parent = self._instance.name
435434

436-
return api.restore_table(
435+
return api._restore_table(
437436
request={"parent": parent, "table_id": table_id, "backup": self.name}
438437
)
439438

0 commit comments

Comments
 (0)