Skip to content

Commit 0fc6877

Browse files
authored
feat: modifies the BigQueryClient proof-of-concept (#2271)
* add copperpenny client. tests to follow in a separate PR * removes old copperpenny client * blackens and lints * removes obsolete test file. new test file to be added in future PR
1 parent eb4f1d1 commit 0fc6877

File tree

7 files changed

+275
-422
lines changed

7 files changed

+275
-422
lines changed

google/cloud/bigquery_v2/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
from .services.routine_service import RoutineServiceClient
2525
from .services.row_access_policy_service import RowAccessPolicyServiceClient
2626
from .services.table_service import TableServiceClient
27-
from .services.centralized_services import BigQueryClient
27+
from .services.centralized_service import BigQueryClient
2828

2929
from .types.biglake_config import BigLakeConfiguration
3030
from .types.clustering import Clustering

google/cloud/bigquery_v2/services/centralized_services/__init__.py renamed to google/cloud/bigquery_v2/services/centralized_service/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@
1515
#
1616
from .client import BigQueryClient
1717

18-
__all__ = ("BigQueryClient",)
18+
__all__ = "BigQueryClient"
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
Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
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+
import os
18+
from typing import (
19+
Optional,
20+
Sequence,
21+
Tuple,
22+
Union,
23+
)
24+
25+
from google.cloud.bigquery_v2.services.centralized_service import _helpers
26+
27+
# Import service client modules
28+
from google.cloud.bigquery_v2.services import (
29+
dataset_service,
30+
job_service,
31+
model_service,
32+
)
33+
34+
# Import types modules (to access *Requests classes)
35+
from google.cloud.bigquery_v2.types import (
36+
dataset,
37+
job,
38+
model,
39+
)
40+
41+
from google.api_core import client_options as client_options_lib
42+
from google.api_core import gapic_v1
43+
from google.api_core import retry as retries
44+
from google.auth import credentials as auth_credentials
45+
46+
# Create a type alias
47+
try:
48+
OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None]
49+
except AttributeError: # pragma: NO COVER
50+
OptionalRetry = Union[retries.Retry, object, None] # type: ignore
51+
52+
# TODO: This line is here to simplify prototyping, etc.
53+
PROJECT_ID = os.environ.get("GOOGLE_CLOUD_PROJECT")
54+
55+
DEFAULT_RETRY: OptionalRetry = gapic_v1.method.DEFAULT
56+
DEFAULT_TIMEOUT: Union[float, object] = gapic_v1.method.DEFAULT
57+
DEFAULT_METADATA: Sequence[Tuple[str, Union[str, bytes]]] = ()
58+
59+
60+
# Create Centralized Client
61+
class BigQueryClient:
62+
def __init__(
63+
self,
64+
*,
65+
credentials: Optional[auth_credentials.Credentials] = None,
66+
client_options: Optional[Union[client_options_lib.ClientOptions, dict]] = None,
67+
):
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+
77+
self._clients["dataset"] = dataset_service.DatasetServiceClient(
78+
credentials=self._credentials, client_options=self._client_options
79+
)
80+
return self._clients["dataset"]
81+
82+
@dataset_service_client.setter
83+
def dataset_service_client(self, value):
84+
# Check for the methods the centralized client exposes (to allow duck-typing)
85+
required_methods = [
86+
"get_dataset",
87+
"insert_dataset",
88+
"patch_dataset",
89+
"update_dataset",
90+
"delete_dataset",
91+
"list_datasets",
92+
"undelete_dataset",
93+
]
94+
for method in required_methods:
95+
if not hasattr(value, method) or not callable(getattr(value, method)):
96+
raise AttributeError(
97+
f"Object assigned to dataset_service_client is missing a callable '{method}' method."
98+
)
99+
self._clients["dataset"] = value
100+
101+
@property
102+
def job_service_client(self):
103+
if "job" not in self._clients:
104+
from google.cloud.bigquery_v2.services import job_service
105+
106+
self._clients["job"] = job_service.JobServiceClient(
107+
credentials=self._credentials, client_options=self._client_options
108+
)
109+
return self._clients["job"]
110+
111+
@job_service_client.setter
112+
def job_service_client(self, value):
113+
required_methods = [
114+
"get_job",
115+
"insert_job",
116+
"cancel_job",
117+
"delete_job",
118+
"list_jobs",
119+
]
120+
for method in required_methods:
121+
if not hasattr(value, method) or not callable(getattr(value, method)):
122+
raise AttributeError(
123+
f"Object assigned to job_service_client is missing a callable '{method}' method."
124+
)
125+
self._clients["job"] = value
126+
127+
@property
128+
def model_service_client(self):
129+
if "model" not in self._clients:
130+
from google.cloud.bigquery_v2.services import model_service
131+
132+
self._clients["model"] = model_service.ModelServiceClient(
133+
credentials=self._credentials, client_options=self._client_options
134+
)
135+
return self._clients["model"]
136+
137+
@model_service_client.setter
138+
def model_service_client(self, value):
139+
required_methods = [
140+
"get_model",
141+
"delete_model",
142+
"patch_model",
143+
"list_models",
144+
]
145+
for method in required_methods:
146+
if not hasattr(value, method) or not callable(getattr(value, method)):
147+
raise AttributeError(
148+
f"Object assigned to model_service_client is missing a callable '{method}' method."
149+
)
150+
self._clients["model"] = value
151+
152+
def get_dataset(
153+
self,
154+
request: Optional[Union[dataset.GetDatasetRequest, dict]] = None,
155+
*,
156+
retry: OptionalRetry = DEFAULT_RETRY,
157+
timeout: Union[float, object] = DEFAULT_TIMEOUT,
158+
metadata: Sequence[Tuple[str, Union[str, bytes]]] = DEFAULT_METADATA,
159+
):
160+
"""
161+
TODO: Docstring is purposefully blank. microgenerator will add automatically.
162+
"""
163+
kwargs = _helpers._drop_self_key(locals())
164+
return self.dataset_service_client.get_dataset(**kwargs)
165+
166+
def list_datasets(
167+
self,
168+
request: Optional[Union[dataset.ListDatasetsRequest, dict]] = None,
169+
*,
170+
retry: OptionalRetry = DEFAULT_RETRY,
171+
timeout: Union[float, object] = DEFAULT_TIMEOUT,
172+
metadata: Sequence[Tuple[str, Union[str, bytes]]] = DEFAULT_METADATA,
173+
):
174+
"""
175+
TODO: Docstring is purposefully blank. microgenerator will add automatically.
176+
"""
177+
kwargs = _helpers._drop_self_key(locals())
178+
return self.dataset_service_client.list_datasets(**kwargs)
179+
180+
def list_jobs(
181+
self,
182+
request: Optional[Union[job.ListJobsRequest, dict]] = None,
183+
*,
184+
retry: OptionalRetry = DEFAULT_RETRY,
185+
timeout: Union[float, object] = DEFAULT_TIMEOUT,
186+
metadata: Sequence[Tuple[str, Union[str, bytes]]] = DEFAULT_METADATA,
187+
):
188+
"""
189+
TODO: Docstring is purposefully blank. microgenerator will add automatically.
190+
"""
191+
kwargs = _helpers._drop_self_key(locals())
192+
return self.job_service_client.list_jobs(**kwargs)
193+
194+
def get_model(
195+
self,
196+
request: Optional[Union[model.GetModelRequest, dict]] = None,
197+
*,
198+
retry: OptionalRetry = DEFAULT_RETRY,
199+
timeout: Union[float, object] = DEFAULT_TIMEOUT,
200+
metadata: Sequence[Tuple[str, Union[str, bytes]]] = DEFAULT_METADATA,
201+
):
202+
"""
203+
TODO: Docstring is purposefully blank. microgenerator will add automatically.
204+
"""
205+
kwargs = _helpers._drop_self_key(locals())
206+
return self.model_service_client.get_model(**kwargs)
207+
208+
def delete_model(
209+
self,
210+
request: Optional[Union[model.DeleteModelRequest, dict]] = None,
211+
*,
212+
retry: OptionalRetry = DEFAULT_RETRY,
213+
timeout: Union[float, object] = DEFAULT_TIMEOUT,
214+
metadata: Sequence[Tuple[str, Union[str, bytes]]] = DEFAULT_METADATA,
215+
):
216+
"""
217+
TODO: Docstring is purposefully blank. microgenerator will add automatically.
218+
"""
219+
kwargs = _helpers._drop_self_key(locals())
220+
# The underlying GAPIC client returns None on success.
221+
return self.model_service_client.delete_model(**kwargs)
222+
223+
def patch_model(
224+
self,
225+
request: Optional[Union[model.PatchModelRequest, dict]] = None,
226+
*,
227+
retry: OptionalRetry = DEFAULT_RETRY,
228+
timeout: Union[float, object] = DEFAULT_TIMEOUT,
229+
metadata: Sequence[Tuple[str, Union[str, bytes]]] = DEFAULT_METADATA,
230+
):
231+
"""
232+
TODO: Docstring is purposefully blank. microgenerator will add automatically.
233+
"""
234+
kwargs = _helpers._drop_self_key(locals())
235+
return self.model_service_client.patch_model(**kwargs)
236+
237+
def list_models(
238+
self,
239+
request: Optional[Union[model.ListModelsRequest, dict]] = None,
240+
*,
241+
retry: OptionalRetry = DEFAULT_RETRY,
242+
timeout: Union[float, object] = DEFAULT_TIMEOUT,
243+
metadata: Sequence[Tuple[str, Union[str, bytes]]] = DEFAULT_METADATA,
244+
):
245+
"""
246+
TODO: Docstring is purposefully blank. microgenerator will add automatically.
247+
"""
248+
kwargs = _helpers._drop_self_key(locals())
249+
return self.model_service_client.list_models(**kwargs)

0 commit comments

Comments
 (0)