Skip to content

Conversation

@gkevinzheng
Copy link
Contributor

Changes Made:

  • Use MutateRow instead of MutateRows for DirectRow.commit instead of Table.MutateRows
  • Added system test for DirectRow.commit because of the decoupling of DirectRow.commit and Table.MutateRows
  • Adjusted input error system test because of slight changes in error behavior
  • Adjusted unit tests for DirectRow.commit

@gkevinzheng gkevinzheng requested review from a team as code owners January 26, 2026 16:30
@product-auto-label product-auto-label bot added the size: m Pull request size is medium. label Jan 26, 2026
@product-auto-label product-auto-label bot added the api: bigtable Issues related to the googleapis/python-bigtable API. label Jan 26, 2026
@gemini-code-assist
Copy link

Summary of Changes

Hello @gkevinzheng, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request refactors the DirectRow.commit method to directly utilize the MutateRow API, moving away from the MutateRows batch operation for single-row commits. This change streamlines the commit process for individual rows and introduces more granular error reporting by translating API exceptions into structured status objects. The update also includes comprehensive testing, with new system tests for DirectRow.commit functionality and adjustments to existing error handling tests to reflect the updated validation logic.

Highlights

  • API Rerouting: The DirectRow.commit method has been rerouted to directly use the MutateRow API call, instead of the MutateRows batch operation, for more efficient single-row mutations.
  • Enhanced Error Handling: Error handling within DirectRow.commit has been improved to catch GoogleAPICallError exceptions and translate them into detailed status_pb2.Status objects, providing clearer error information.
  • New System Test: A new system test, test_table_direct_row_commit, was added to comprehensively validate the functionality of DirectRow.commit for various mutation types, including setting, deleting cells, and deleting entire rows.
  • Adjusted Error Validation Logic: System tests for input errors were updated to reflect changes in validation. Exceeding MAX_MUTATIONS is now expected to result in a server-side INVALID_ARGUMENT status, while committing with no mutations now triggers a client-side ValueError.
  • Unit Test Alignment: Unit tests for DirectRow.commit were updated to align with the new mutate_row API interaction and to thoroughly test the new error handling mechanisms, including specific tests for InternalServerError and generic GoogleAPICallError.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

The pull request successfully reroutes DirectRow.commit to use MutateRow as intended, which simplifies the mutation process for single rows. The changes in google/cloud/bigtable/row.py correctly implement the new API call and handle exceptions by converting them into status_pb2.Status objects. The system and unit tests have been appropriately updated to reflect these changes, including new tests for DirectRow.commit and adjustments to error handling tests. However, there's an inconsistency in mutation validation strategy across Row subclasses. While DirectRow.commit now relies on the underlying gRPC client for validating empty mutation lists and MAX_MUTATIONS, ConditionalRow.commit still performs these checks client-side. This difference could lead to varied error behaviors and should be addressed for better maintainability and predictability.

Comment on lines 468 to 479
try:
self._table._table_impl.mutate_row(self.row_key, self._get_mutations())
return status_pb2.Status()
except GoogleAPICallError as e:
# If the RPC call returns an error, extract the error into a status object, if possible.
return status_pb2.Status(
code=e.grpc_status_code.value[0]
if e.grpc_status_code is not None
else code_pb2.UNKNOWN,
message=e.message,
details=e.details,
)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The DirectRow.commit method now relies on the underlying _table_impl.mutate_row to validate the number of mutations and handle empty mutation lists. This is a change from the previous client-side validation for MAX_MUTATIONS. However, ConditionalRow.commit (lines 591-602 in the full file) still performs client-side checks for MAX_MUTATIONS and returns early for empty mutation lists. This inconsistency in validation strategy across Row subclasses could lead to varied error behaviors and should be addressed for better maintainability and predictability. Consider aligning the validation approach for ConditionalRow.commit with DirectRow.commit, or reintroducing explicit client-side validation in DirectRow.commit if that is the desired behavior for all Row types.

Comment on lines 1095 to 1098
# Not having any mutations gives a ValueError enforced on the client side.
row.clear()
with pytest.raises(InvalidArgument):
with pytest.raises(ValueError):
row.commit()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The comment on line 1095 states, "Not having any mutations gives a ValueError enforced on the client side." However, the DirectRow.commit method in google/cloud/bigtable/row.py does not explicitly contain this validation logic; it relies on the underlying _table_impl.mutate_row call to raise an error for empty mutations. To ensure the comment accurately reflects the code's behavior, either add explicit client-side validation for empty mutations within DirectRow.commit (for consistency with ConditionalRow.commit), or update this comment to clarify that the ValueError originates from the underlying API client.

@gkevinzheng gkevinzheng added the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Jan 26, 2026
@yoshi-kokoro yoshi-kokoro removed the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Jan 26, 2026
return response[0]
try:
self._table._table_impl.mutate_row(self.row_key, self._get_mutations())
return status_pb2.Status()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Conisder this for clarity

Suggested change
return status_pb2.Status()
return status_pb2.Status(code_pb2.OK)


return response[0]
try:
self._table._table_impl.mutate_row(self.row_key, self._get_mutations())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docstring says "If no mutations have been created in the row, no request is made.". But it looks like mutate_row raises a ValueError if no mutations are present.

You should probably catch and swallow that exception, and make sure this case is handled in tests


return response[0]
try:
self._table._table_impl.mutate_row(self.row_key, self._get_mutations())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mutate_row has automatic retries. Is that expected? Did the previous implementation retry?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous implementation used Table.mutate_rows with the default retry.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api: bigtable Issues related to the googleapis/python-bigtable API. size: m Pull request size is medium.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants