Skip to content

Commit f561799

Browse files
authored
feat: custom query labels for compute options (#638)
* feat: Custom query labels for compute options * Update docstring * Update test * Code example update. * ignore type * update format
1 parent 36578ab commit f561799

File tree

3 files changed

+76
-1
lines changed

3 files changed

+76
-1
lines changed

bigframes/_config/compute_options.py

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"""Options for displaying objects."""
1616

1717
import dataclasses
18-
from typing import Optional
18+
from typing import Any, Dict, Optional
1919

2020

2121
@dataclasses.dataclass
@@ -34,6 +34,26 @@ class ComputeOptions:
3434
3535
>>> bpd.options.compute.maximum_bytes_billed = None # reset option
3636
37+
To add multiple extra labels to a query configuration, use the `assign_extra_query_labels`
38+
method with keyword arguments:
39+
40+
>>> bpd.options.compute.assign_extra_query_labels(test1=1, test2="abc")
41+
>>> bpd.options.compute.extra_query_labels
42+
{'test1': 1, 'test2': 'abc'}
43+
44+
Alternatively, you can add labels individually by directly accessing the `extra_query_labels`
45+
dictionary:
46+
47+
>>> bpd.options.compute.extra_query_labels["test3"] = False
48+
>>> bpd.options.compute.extra_query_labels
49+
{'test1': 1, 'test2': 'abc', 'test3': False}
50+
51+
To remove a label from the configuration, use the `del` keyword on the desired label key:
52+
53+
>>> del bpd.options.compute.extra_query_labels["test1"]
54+
>>> bpd.options.compute.extra_query_labels
55+
{'test2': 'abc', 'test3': False}
56+
3757
Attributes:
3858
maximum_bytes_billed (int, Options):
3959
Limits the bytes billed for query jobs. Queries that will have
@@ -44,7 +64,38 @@ class ComputeOptions:
4464
If enabled, large queries may be factored into multiple smaller queries
4565
in order to avoid generating queries that are too complex for the query
4666
engine to handle. However this comes at the cost of increase cost and latency.
67+
extra_query_labels (Dict[str, Any], Options):
68+
Stores additional custom labels for query configuration.
4769
"""
4870

4971
maximum_bytes_billed: Optional[int] = None
5072
enable_multi_query_execution: bool = False
73+
extra_query_labels: Dict[str, Any] = dataclasses.field(
74+
default_factory=dict, init=False
75+
)
76+
77+
def assign_extra_query_labels(self, **kwargs: Any) -> None:
78+
"""
79+
Assigns additional custom labels for query configuration. The method updates the
80+
`extra_query_labels` dictionary with new labels provided through keyword arguments.
81+
82+
Args:
83+
kwargs (Any):
84+
Custom labels provided as keyword arguments. Each key-value pair
85+
in `kwargs` represents a label name and its value.
86+
87+
Raises:
88+
ValueError: If a key matches one of the reserved attribute names,
89+
specifically 'maximum_bytes_billed' or 'enable_multi_query_execution',
90+
to prevent conflicts with built-in settings.
91+
"""
92+
reserved_keys = ["maximum_bytes_billed", "enable_multi_query_execution"]
93+
for key in kwargs:
94+
if key in reserved_keys:
95+
raise ValueError(
96+
f"'{key}' is a reserved attribute name. Please use "
97+
"a different key for your custom labels to avoid "
98+
"conflicts with built-in settings."
99+
)
100+
101+
self.extra_query_labels.update(kwargs)

bigframes/session/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1699,6 +1699,12 @@ def _prepare_query_job_config(
16991699
bigframes.options.compute.maximum_bytes_billed
17001700
)
17011701

1702+
current_labels = job_config.labels if job_config.labels else {}
1703+
for key, value in bigframes.options.compute.extra_query_labels.items():
1704+
if key not in current_labels:
1705+
current_labels[key] = value
1706+
job_config.labels = current_labels
1707+
17021708
if self._bq_kms_key_name:
17031709
job_config.destination_encryption_configuration = (
17041710
bigquery.EncryptionConfiguration(kms_key_name=self._bq_kms_key_name)

tests/system/small/test_session.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,24 @@ def test_read_gbq_with_configuration(
405405
assert df.shape == (9, 3)
406406

407407

408+
def test_read_gbq_with_custom_global_labels(
409+
session: bigframes.Session, scalars_table_id: str
410+
):
411+
bigframes.options.compute.assign_extra_query_labels(test1=1, test2="abc")
412+
bigframes.options.compute.extra_query_labels["test3"] = False
413+
414+
job_labels = session.read_gbq(scalars_table_id).query_job.labels # type:ignore
415+
expected_labels = {"test1": "1", "test2": "abc", "test3": "false"}
416+
417+
assert all(job_labels.get(key) == value for key, value in expected_labels.items())
418+
419+
del bigframes.options.compute.extra_query_labels["test1"]
420+
del bigframes.options.compute.extra_query_labels["test2"]
421+
del bigframes.options.compute.extra_query_labels["test3"]
422+
423+
assert len(bigframes.options.compute.extra_query_labels) == 0
424+
425+
408426
def test_read_gbq_model(session, penguins_linear_model_name):
409427
model = session.read_gbq_model(penguins_linear_model_name)
410428
assert isinstance(model, bigframes.ml.linear_model.LinearRegression)

0 commit comments

Comments
 (0)