Skip to content

Commit 2f58514

Browse files
authored
Merge branch 'main' into feat-dataset-view
2 parents ee1afbc + eb9c2af commit 2f58514

File tree

3 files changed

+133
-3
lines changed

3 files changed

+133
-3
lines changed

google/cloud/bigquery/client.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@
9090
from google.cloud.bigquery.dataset import Dataset
9191
from google.cloud.bigquery.dataset import DatasetListItem
9292
from google.cloud.bigquery.dataset import DatasetReference
93-
from google.cloud.bigquery.enums import AutoRowIDs, DatasetView
93+
94+
from google.cloud.bigquery.enums import AutoRowIDs, DatasetView, UpdateMode
9495
from google.cloud.bigquery.format_options import ParquetOptions
9596
from google.cloud.bigquery.job import (
9697
CopyJob,
@@ -1220,6 +1221,7 @@ def update_dataset(
12201221
fields: Sequence[str],
12211222
retry: retries.Retry = DEFAULT_RETRY,
12221223
timeout: TimeoutType = DEFAULT_TIMEOUT,
1224+
update_mode: Optional[UpdateMode] = None,
12231225
) -> Dataset:
12241226
"""Change some fields of a dataset.
12251227
@@ -1259,6 +1261,20 @@ def update_dataset(
12591261
timeout (Optional[float]):
12601262
The number of seconds to wait for the underlying HTTP transport
12611263
before using ``retry``.
1264+
update_mode (Optional[google.cloud.bigquery.enums.UpdateMode]):
1265+
Specifies the kind of information to update in a dataset.
1266+
By default, dataset metadata (e.g. friendlyName, description,
1267+
labels, etc) and ACL information are updated. This argument can
1268+
take on the following possible enum values.
1269+
1270+
* :attr:`~google.cloud.bigquery.enums.UPDATE_MODE_UNSPECIFIED`:
1271+
The default value. Behavior defaults to UPDATE_FULL.
1272+
* :attr:`~google.cloud.bigquery.enums.UpdateMode.UPDATE_METADATA`:
1273+
Includes metadata information for the dataset, such as friendlyName, description, labels, etc.
1274+
* :attr:`~google.cloud.bigquery.enums.UpdateMode.UPDATE_ACL`:
1275+
Includes ACL information for the dataset, which defines dataset access for one or more entities.
1276+
* :attr:`~google.cloud.bigquery.enums.UpdateMode.UPDATE_FULL`:
1277+
Includes both dataset metadata and ACL information.
12621278
12631279
Returns:
12641280
google.cloud.bigquery.dataset.Dataset:
@@ -1272,6 +1288,11 @@ def update_dataset(
12721288
path = dataset.path
12731289
span_attributes = {"path": path, "fields": fields}
12741290

1291+
if update_mode:
1292+
query_params = {"updateMode": update_mode.value}
1293+
else:
1294+
query_params = {}
1295+
12751296
api_response = self._call_api(
12761297
retry,
12771298
span_name="BigQuery.updateDataset",
@@ -1281,6 +1302,7 @@ def update_dataset(
12811302
data=partial,
12821303
headers=headers,
12831304
timeout=timeout,
1305+
query_params=query_params,
12841306
)
12851307
return Dataset.from_api_repr(api_response)
12861308

google/cloud/bigquery/enums.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,24 @@ class BigLakeTableFormat(object):
427427
"""Apache Iceberg format."""
428428

429429

430+
class UpdateMode(enum.Enum):
431+
"""Specifies the kind of information to update in a dataset."""
432+
433+
UPDATE_MODE_UNSPECIFIED = "UPDATE_MODE_UNSPECIFIED"
434+
"""The default value. Behavior defaults to UPDATE_FULL."""
435+
436+
UPDATE_METADATA = "UPDATE_METADATA"
437+
"""Includes metadata information for the dataset, such as friendlyName,
438+
description, labels, etc."""
439+
440+
UPDATE_ACL = "UPDATE_ACL"
441+
"""Includes ACL information for the dataset, which defines dataset access
442+
for one or more entities."""
443+
444+
UPDATE_FULL = "UPDATE_FULL"
445+
"""Includes both dataset metadata and ACL information."""
446+
447+
430448
class JobCreationMode(object):
431449
"""Documented values for Job Creation Mode."""
432450

tests/unit/test_client.py

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@
6060

6161
from google.cloud.bigquery import job as bqjob
6262
import google.cloud.bigquery._job_helpers
63-
from google.cloud.bigquery.dataset import DatasetReference
64-
from google.cloud.bigquery.enums import DatasetView
63+
from google.cloud.bigquery.dataset import DatasetReference, Dataset
64+
from google.cloud.bigquery.enums import UpdateMode, DatasetView
6565
from google.cloud.bigquery import exceptions
6666
from google.cloud.bigquery import ParquetOptions
6767
import google.cloud.bigquery.retry
@@ -2168,6 +2168,7 @@ def test_update_dataset(self):
21682168
},
21692169
path="/" + PATH,
21702170
timeout=7.5,
2171+
query_params={},
21712172
)
21722173
self.assertEqual(ds2.description, ds.description)
21732174
self.assertEqual(ds2.friendly_name, ds.friendly_name)
@@ -2181,6 +2182,94 @@ def test_update_dataset(self):
21812182
client.update_dataset(ds, [])
21822183
req = conn.api_request.call_args
21832184
self.assertEqual(req[1]["headers"]["If-Match"], "etag")
2185+
self.assertEqual(req[1].get("query_params"), {})
2186+
2187+
def test_update_dataset_w_update_mode(self):
2188+
PATH = f"projects/{self.PROJECT}/datasets/{self.DS_ID}"
2189+
creds = _make_credentials()
2190+
client = self._make_one(project=self.PROJECT, credentials=creds)
2191+
2192+
DESCRIPTION = "DESCRIPTION"
2193+
RESOURCE = {
2194+
"datasetReference": {"projectId": self.PROJECT, "datasetId": self.DS_ID},
2195+
"etag": "etag",
2196+
"description": DESCRIPTION,
2197+
}
2198+
dataset_ref = DatasetReference(self.PROJECT, self.DS_ID)
2199+
orig_dataset = Dataset(dataset_ref)
2200+
orig_dataset.description = DESCRIPTION
2201+
filter_fields = ["description"]
2202+
2203+
test_cases = [
2204+
(None, None),
2205+
(UpdateMode.UPDATE_MODE_UNSPECIFIED, "UPDATE_MODE_UNSPECIFIED"),
2206+
(UpdateMode.UPDATE_METADATA, "UPDATE_METADATA"),
2207+
(UpdateMode.UPDATE_ACL, "UPDATE_ACL"),
2208+
(UpdateMode.UPDATE_FULL, "UPDATE_FULL"),
2209+
]
2210+
2211+
for update_mode_arg, expected_param_value in test_cases:
2212+
with self.subTest(
2213+
update_mode_arg=update_mode_arg,
2214+
expected_param_value=expected_param_value,
2215+
):
2216+
conn = client._connection = make_connection(RESOURCE, RESOURCE)
2217+
2218+
new_dataset = client.update_dataset(
2219+
orig_dataset,
2220+
fields=filter_fields,
2221+
update_mode=update_mode_arg,
2222+
)
2223+
self.assertEqual(orig_dataset.description, new_dataset.description)
2224+
2225+
if expected_param_value:
2226+
expected_query_params = {"updateMode": expected_param_value}
2227+
else:
2228+
expected_query_params = {}
2229+
2230+
conn.api_request.assert_called_once_with(
2231+
method="PATCH",
2232+
path="/" + PATH,
2233+
data={"description": DESCRIPTION},
2234+
timeout=DEFAULT_TIMEOUT,
2235+
query_params=expected_query_params if expected_query_params else {},
2236+
)
2237+
2238+
def test_update_dataset_w_invalid_update_mode(self):
2239+
creds = _make_credentials()
2240+
client = self._make_one(project=self.PROJECT, credentials=creds)
2241+
2242+
DESCRIPTION = "DESCRIPTION"
2243+
resource = {
2244+
"datasetReference": {"projectId": self.PROJECT, "datasetId": self.DS_ID},
2245+
"etag": "etag",
2246+
}
2247+
2248+
dataset_ref = DatasetReference(self.PROJECT, self.DS_ID)
2249+
orig_dataset = Dataset(dataset_ref)
2250+
orig_dataset.description = DESCRIPTION
2251+
filter_fields = ["description"] # A non-empty list of fields is required
2252+
2253+
# Mock the connection to prevent actual API calls
2254+
# and to provide a minimal valid response if the call were to proceed.
2255+
conn = client._connection = make_connection(resource)
2256+
2257+
test_cases = [
2258+
"INVALID_STRING",
2259+
123,
2260+
123.45,
2261+
object(),
2262+
]
2263+
2264+
for invalid_update_mode in test_cases:
2265+
with self.subTest(invalid_update_mode=invalid_update_mode):
2266+
conn.api_request.reset_mock() # Reset mock for each sub-test
2267+
with self.assertRaises(AttributeError):
2268+
client.update_dataset(
2269+
orig_dataset,
2270+
fields=filter_fields,
2271+
update_mode=invalid_update_mode,
2272+
)
21842273

21852274
def test_update_dataset_w_custom_property(self):
21862275
# The library should handle sending properties to the API that are not
@@ -2212,6 +2301,7 @@ def test_update_dataset_w_custom_property(self):
22122301
data={"newAlphaProperty": "unreleased property"},
22132302
path=path,
22142303
timeout=DEFAULT_TIMEOUT,
2304+
query_params={},
22152305
)
22162306

22172307
self.assertEqual(dataset.dataset_id, self.DS_ID)

0 commit comments

Comments
 (0)