Skip to content

Commit 0a1a63e

Browse files
committed
adds helper file and refactors init and properties and setters
1 parent e608e95 commit 0a1a63e

File tree

3 files changed

+134
-30
lines changed

3 files changed

+134
-30
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# -*- coding: utf-8 -*-
2+
# Copyright 2025 Google LLC
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#
16+
17+
18+
def _drop_self_key(kwargs):
19+
"Drops 'self' key from a given kwargs dict."
20+
21+
if not isinstance(kwargs, dict):
22+
raise TypeError("kwargs must be a dict.")
23+
kwargs.pop("self", None) # Essentially a no-op if 'self' key does not exist
24+
return kwargs

google/cloud/bigquery_v2/services/centralized_service/client.py

Lines changed: 101 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
Union,
2323
)
2424

25+
from google.cloud.bigquery_v2.services.centralized_service import _helpers
26+
2527
# Import service client modules
2628
from google.cloud.bigquery_v2.services import (
2729
dataset_service,
@@ -55,15 +57,6 @@
5557
DEFAULT_METADATA: Sequence[Tuple[str, Union[str, bytes]]] = ()
5658

5759

58-
def _drop_self_key(kwargs):
59-
"Drops 'self' key from a given kwargs dict."
60-
61-
if not isinstance(kwargs, dict):
62-
raise TypeError("kwargs must be a dict.")
63-
kwargs.pop("self", None) # Essentially a no-op if 'self' key does not exist
64-
return kwargs
65-
66-
6760
# Create Centralized Client
6861
class BigQueryClient:
6962
def __init__(
@@ -72,19 +65,86 @@ def __init__(
7265
credentials: Optional[auth_credentials.Credentials] = None,
7366
client_options: Optional[Union[client_options_lib.ClientOptions, dict]] = None,
7467
):
75-
# A dictionary mapping service names to their client classes.
76-
service_clients_config = {
77-
"dataset": dataset_service.DatasetServiceClient,
78-
"job": job_service.JobServiceClient,
79-
"model": model_service.ModelServiceClient,
80-
}
81-
82-
# Dynamically initialize service clients.
83-
for service_name, client_class in service_clients_config.items():
84-
client_instance = client_class(
85-
credentials=credentials, client_options=client_options
68+
self._clients = {}
69+
self._credentials = credentials
70+
self._client_options = client_options
71+
72+
@property
73+
def dataset_service_client(self):
74+
if "dataset" not in self._clients:
75+
from google.cloud.bigquery_v2.services import dataset_service
76+
self._clients["dataset"] = dataset_service.DatasetServiceClient(
77+
credentials=self._credentials, client_options=self._client_options
8678
)
87-
setattr(self, f"{service_name}_service_client", client_instance)
79+
return self._clients["dataset"]
80+
81+
@dataset_service_client.setter
82+
def dataset_service_client(self, value):
83+
# Check for the methods that this class most commonly uses (duck typing)
84+
required_methods = [
85+
"get_dataset",
86+
"insert_dataset",
87+
"patch_dataset",
88+
"update_dataset",
89+
"delete_dataset",
90+
"list_datasets",
91+
"undelete_dataset",
92+
]
93+
for method in required_methods:
94+
if not hasattr(value, method) or not callable(getattr(value, method)):
95+
raise AttributeError(
96+
f"Object assigned to dataset_service_client is missing a callable '{method}' method."
97+
)
98+
self._clients["dataset"] = value
99+
100+
@property
101+
def job_service_client(self):
102+
if "job" not in self._clients:
103+
from google.cloud.bigquery_v2.services import job_service
104+
self._clients["job"] = job_service.JobServiceClient(
105+
credentials=self._credentials, client_options=self._client_options
106+
)
107+
return self._clients["job"]
108+
109+
@job_service_client.setter
110+
def job_service_client(self, value):
111+
required_methods = [
112+
"get_job",
113+
"insert_job",
114+
"cancel_job",
115+
"delete_job",
116+
"list_jobs",
117+
]
118+
for method in required_methods:
119+
if not hasattr(value, method) or not callable(getattr(value, method)):
120+
raise AttributeError(
121+
f"Object assigned to job_service_client is missing a callable '{method}' method."
122+
)
123+
self._clients["job"] = value
124+
125+
@property
126+
def model_service_client(self):
127+
if "model" not in self._clients:
128+
from google.cloud.bigquery_v2.services import model_service
129+
self._clients["model"] = model_service.ModelServiceClient(
130+
credentials=self._credentials, client_options=self._client_options
131+
)
132+
return self._clients["model"]
133+
134+
@model_service_client.setter
135+
def model_service_client(self, value):
136+
required_methods = [
137+
"get_model",
138+
"delete_model",
139+
"patch_model",
140+
"list_models",
141+
]
142+
for method in required_methods:
143+
if not hasattr(value, method) or not callable(getattr(value, method)):
144+
raise AttributeError(
145+
f"Object assigned to model_service_client is missing a callable '{method}' method."
146+
)
147+
self._clients["model"] = value
88148

89149
def get_dataset(
90150
self,
@@ -97,9 +157,23 @@ def get_dataset(
97157
"""
98158
TODO: Docstring is purposefully blank. microgenerator will add automatically.
99159
"""
100-
kwargs = _drop_self_key(locals())
160+
kwargs = _helpers._drop_self_key(locals())
101161
return self.dataset_service_client.get_dataset(**kwargs)
102162

163+
def list_datasets(
164+
self,
165+
request: Optional[Union[dataset.ListDatasetsRequest, dict]] = None,
166+
*,
167+
retry: OptionalRetry = DEFAULT_RETRY,
168+
timeout: Union[float, object] = DEFAULT_TIMEOUT,
169+
metadata: Sequence[Tuple[str, Union[str, bytes]]] = DEFAULT_METADATA,
170+
):
171+
"""
172+
TODO: Docstring is purposefully blank. microgenerator will add automatically.
173+
"""
174+
kwargs = _helpers._drop_self_key(locals())
175+
return self.dataset_service_client.list_datasets(**kwargs)
176+
103177
def list_jobs(
104178
self,
105179
request: Optional[Union[job.ListJobsRequest, dict]] = None,
@@ -111,7 +185,7 @@ def list_jobs(
111185
"""
112186
TODO: Docstring is purposefully blank. microgenerator will add automatically.
113187
"""
114-
kwargs = _drop_self_key(locals())
188+
kwargs = _helpers._drop_self_key(locals())
115189
return self.job_service_client.list_jobs(**kwargs)
116190

117191
def get_model(
@@ -125,7 +199,7 @@ def get_model(
125199
"""
126200
TODO: Docstring is purposefully blank. microgenerator will add automatically.
127201
"""
128-
kwargs = _drop_self_key(locals())
202+
kwargs = _helpers._drop_self_key(locals())
129203
return self.model_service_client.get_model(**kwargs)
130204

131205
def delete_model(
@@ -139,7 +213,7 @@ def delete_model(
139213
"""
140214
TODO: Docstring is purposefully blank. microgenerator will add automatically.
141215
"""
142-
kwargs = _drop_self_key(locals())
216+
kwargs = _helpers._drop_self_key(locals())
143217
# The underlying GAPIC client returns None on success.
144218
return self.model_service_client.delete_model(**kwargs)
145219

@@ -154,7 +228,7 @@ def patch_model(
154228
"""
155229
TODO: Docstring is purposefully blank. microgenerator will add automatically.
156230
"""
157-
kwargs = _drop_self_key(locals())
231+
kwargs = _helpers._drop_self_key(locals())
158232
return self.model_service_client.patch_model(**kwargs)
159233

160234
def list_models(
@@ -168,5 +242,5 @@ def list_models(
168242
"""
169243
TODO: Docstring is purposefully blank. microgenerator will add automatically.
170244
"""
171-
kwargs = _drop_self_key(locals())
245+
kwargs = _helpers._drop_self_key(locals())
172246
return self.model_service_client.list_models(**kwargs)

tests/unit/gapic/bigquery_v2/test_centralized_service.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,15 +172,21 @@ def test_client_initialization_arguments(
172172
)
173173

174174
# Assert
175-
# The BigQueryClient should have been initialized, and the underlying
176-
# service clients should have been instantiated with the provided arguments.
177-
# Note: We are asserting on the mock objects provided by the fixtures.
175+
# The BigQueryClient should have been initialized. Accessing the
176+
# service client properties should instantiate them with the correct arguments.
177+
178+
# Access the property to trigger instantiation
179+
_ = client.dataset_service_client
178180
mock_dataset_service_client.assert_called_once_with(
179181
credentials=credentials, client_options=client_options
180182
)
183+
184+
_ = client.job_service_client
181185
mock_job_service_client.assert_called_once_with(
182186
credentials=credentials, client_options=client_options
183187
)
188+
189+
_ = client.model_service_client
184190
mock_model_service_client.assert_called_once_with(
185191
credentials=credentials, client_options=client_options
186192
)

0 commit comments

Comments
 (0)