Skip to content

Conversation

@googlyrahman
Copy link

This PR introduces an abstract class to support the upcoming async client for the Python SDK. This refactor defines the public interface and enables code sharing between sync and async client, without introducing new logic.

@product-auto-label product-auto-label bot added size: l Pull request size is large. api: storage Issues related to the googleapis/python-storage API. labels Dec 8, 2025
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @googlyrahman, 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 introduces a foundational architectural change to the Python storage client by creating an abstract BaseClient class. This new class centralizes and standardizes the complex initialization logic, including API endpoint resolution, credential management, and project configuration, which was previously embedded directly within the Client class. The Client class now inherits from this BaseClient, streamlining its constructor and promoting a cleaner, more maintainable codebase. This strategic refactor is crucial for enabling the future development of an asynchronous client, ensuring a unified interface and maximizing code reuse across different client implementations.

Highlights

  • New Abstract BaseClient: Introduced a new abstract class BaseClient in google/cloud/storage/abstracts/base_client.py. This class serves as a common base for storage clients, encapsulating shared initialization logic.
  • Client Refactoring: The existing Client class in google/cloud/storage/client.py has been refactored to inherit from the new BaseClient. This significantly simplifies its __init__ method by delegating common setup tasks to the base class.
  • Centralized Initialization Logic: Common client initialization concerns, such as API endpoint determination (including emulator and universe domain handling), credential processing, and project configuration, have been moved into the BaseClient. This reduces code duplication and ensures consistent behavior across client implementations.
  • Preparation for Async Client: This refactoring lays the groundwork for an upcoming asynchronous client for the Python SDK. By defining a common abstract base, it ensures a consistent public interface and enables code sharing between synchronous and asynchronous clients.
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
Contributor

@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 introduces a new abstract base class, BaseClient, in google/cloud/storage/abstracts/base_client.py to centralize client initialization logic, including project handling, API endpoint determination, credential management, and universe domain validation. The existing Client class in google/cloud/storage/client.py is refactored to inherit from BaseClient, significantly simplifying its __init__ method by delegating these responsibilities to the superclass. Review comments suggest improving the BaseClient's __init__ method by changing a mutable default argument for extra_headers to None, simplifying a boolean assignment for _is_emulator_set, and reordering imports according to PEP 8. Additionally, a comment in the Client class regarding connection_kw_args is recommended for removal.

client_info=None,
client_options=None,
use_auth_w_custom_endpoint=True,
extra_headers={},
Copy link
Contributor

Choose a reason for hiding this comment

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

high

Using a mutable default argument like {} can lead to unexpected behavior. If this dictionary is modified, the change will persist across all subsequent calls to this function that don't specify extra_headers. It's safer to use None as the default and initialize an empty dictionary inside the function, for example by adding if extra_headers is None: extra_headers = {} at the beginning of the __init__ method.

Suggested change
extra_headers={},
extra_headers=None,

Comment on lines +16 to +28
from google.cloud.storage._helpers import _get_api_endpoint_override
from google.cloud.storage._helpers import _get_environ_project
from google.cloud.storage._helpers import _get_storage_emulator_override
from google.cloud.storage._helpers import _DEFAULT_SCHEME
from google.cloud.storage._helpers import _STORAGE_HOST_TEMPLATE
from google.auth.credentials import AnonymousCredentials
from google.cloud.client import ClientWithProject
from google.cloud._helpers import _LocalStack
from google.auth.transport import mtls
from abc import ABC

import os
import google.api_core
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The imports are not ordered according to PEP 8 guidelines. They should be grouped into standard library, third-party, and local application imports, with each group sorted alphabetically.

Suggested change
from google.cloud.storage._helpers import _get_api_endpoint_override
from google.cloud.storage._helpers import _get_environ_project
from google.cloud.storage._helpers import _get_storage_emulator_override
from google.cloud.storage._helpers import _DEFAULT_SCHEME
from google.cloud.storage._helpers import _STORAGE_HOST_TEMPLATE
from google.auth.credentials import AnonymousCredentials
from google.cloud.client import ClientWithProject
from google.cloud._helpers import _LocalStack
from google.auth.transport import mtls
from abc import ABC
import os
import google.api_core
from abc import ABC
import os
import google.api_core
from google.auth.credentials import AnonymousCredentials
from google.auth.transport import mtls
from google.cloud._helpers import _LocalStack
from google.cloud.client import ClientWithProject
from google.cloud.storage._helpers import _DEFAULT_SCHEME
from google.cloud.storage._helpers import _get_api_endpoint_override
from google.cloud.storage._helpers import _get_environ_project
from google.cloud.storage._helpers import _get_storage_emulator_override
from google.cloud.storage._helpers import _STORAGE_HOST_TEMPLATE

api_endpoint = None

connection_kw_args["api_endpoint"] = api_endpoint
self._is_emulator_set = True if storage_emulator_override else False
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This can be simplified by directly converting the value to a boolean.

Suggested change
self._is_emulator_set = True if storage_emulator_override else False
self._is_emulator_set = bool(storage_emulator_override)


# Pass extra_headers to Connection
connection = Connection(self, **connection_kw_args)
connection = Connection(self, **self.connection_kw_args) # connection_kw_args would always be set in base class
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This comment seems to be a note for the developer and could be removed to keep the code cleaner. The fact that self.connection_kw_args is set in the base class should be clear from the class structure.

Suggested change
connection = Connection(self, **self.connection_kw_args) # connection_kw_args would always be set in base class
connection = Connection(self, **self.connection_kw_args)

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

Labels

api: storage Issues related to the googleapis/python-storage API. size: l Pull request size is large.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant