From d36dbf4e7ff4f59fcdb70cec4328da059fab45b7 Mon Sep 17 00:00:00 2001 From: Seth Hollyman Date: Mon, 19 May 2025 17:56:52 +0000 Subject: [PATCH 01/12] feat: job creation mode GA This PR makes the underlying functionality related to how queries can optionally avoid job creation a GA feature. It does the following: * no longer uses the preview QUERY_PREVIEW_ENABLED environment variable to control job creation * adds a new argument to Client instantiation to control job creation mode * adds a property/setter to Client to control job creation mode This PR also updates/renames the sample demonstrating how to leverage job creation mode with Client.query_and_wait. --- google/cloud/bigquery/_job_helpers.py | 11 ++------- google/cloud/bigquery/client.py | 22 +++++++++++------ google/cloud/bigquery/enums.py | 19 +++++++++++++++ ...rtmode.py => client_query_job_optional.py} | 24 +++++++++++-------- ...e.py => test_client_query_job_optional.py} | 6 ++--- tests/unit/test__job_helpers.py | 12 +++++----- 6 files changed, 59 insertions(+), 35 deletions(-) rename samples/{client_query_shortmode.py => client_query_job_optional.py} (69%) rename samples/tests/{test_client_query_shortmode.py => test_client_query_job_optional.py} (85%) diff --git a/google/cloud/bigquery/_job_helpers.py b/google/cloud/bigquery/_job_helpers.py index 4a884ada5..ee2fc6be7 100644 --- a/google/cloud/bigquery/_job_helpers.py +++ b/google/cloud/bigquery/_job_helpers.py @@ -400,12 +400,6 @@ def query_and_wait( ) -> table.RowIterator: """Run the query, wait for it to finish, and return the results. - While ``jobCreationMode=JOB_CREATION_OPTIONAL`` is in preview in the - ``jobs.query`` REST API, use the default ``jobCreationMode`` unless - the environment variable ``QUERY_PREVIEW_ENABLED=true``. After - ``jobCreationMode`` is GA, this method will always use - ``jobCreationMode=JOB_CREATION_OPTIONAL``. See: - https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/query Args: client: @@ -500,9 +494,8 @@ def query_and_wait( request_body["maxResults"] = min(page_size, max_results) elif page_size is not None or max_results is not None: request_body["maxResults"] = page_size or max_results - - if os.getenv("QUERY_PREVIEW_ENABLED", "").casefold() == "true": - request_body["jobCreationMode"] = "JOB_CREATION_OPTIONAL" + if client.default_job_creation_mode: + request_body["jobCreationMode"] = client.default_job_creation_mode def do_query(): request_body["requestId"] = make_job_id() diff --git a/google/cloud/bigquery/client.py b/google/cloud/bigquery/client.py index 8ad1586f4..72546a1ff 100644 --- a/google/cloud/bigquery/client.py +++ b/google/cloud/bigquery/client.py @@ -221,6 +221,10 @@ class Client(ClientWithProject): client_options (Optional[Union[google.api_core.client_options.ClientOptions, Dict]]): Client options used to set user options on the client. API Endpoint should be set through client_options. + default_job_creation_mode (Optional[str]): + Sets the default job creation mode used by query methods such as + query_and_wait(). For lightweight queries, JOB_CREATION_OPTIONAL is + generally recommended. Raises: google.auth.exceptions.DefaultCredentialsError: @@ -243,6 +247,7 @@ def __init__( client_options: Optional[ Union[google.api_core.client_options.ClientOptions, Dict[str, Any]] ] = None, + default_job_creation_mode: Optional[str] = None, ) -> None: if client_options is None: client_options = {} @@ -277,6 +282,7 @@ def __init__( self._connection = Connection(self, **kw_args) self._location = location self._default_load_job_config = copy.deepcopy(default_load_job_config) + self._default_job_creation_mode = default_job_creation_mode # Use property setter so validation can run. self.default_query_job_config = default_query_job_config @@ -286,6 +292,15 @@ def location(self): """Default location for jobs / datasets / tables.""" return self._location + @property + def default_job_creation_mode(self): + """Default job creation mode used for query execution.""" + return self._default_job_creation_mode + + @default_job_creation_mode.setter + def default_job_creation_mode(self, value: Optional[str]): + self._default_job_creation_mode = value + @property def default_query_job_config(self) -> Optional[QueryJobConfig]: """Default ``QueryJobConfig`` or ``None``. @@ -3532,13 +3547,6 @@ def query_and_wait( ) -> RowIterator: """Run the query, wait for it to finish, and return the results. - While ``jobCreationMode=JOB_CREATION_OPTIONAL`` is in preview in the - ``jobs.query`` REST API, use the default ``jobCreationMode`` unless - the environment variable ``QUERY_PREVIEW_ENABLED=true``. After - ``jobCreationMode`` is GA, this method will always use - ``jobCreationMode=JOB_CREATION_OPTIONAL``. See: - https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/query - Args: query (str): SQL query to be executed. Defaults to the standard SQL diff --git a/google/cloud/bigquery/enums.py b/google/cloud/bigquery/enums.py index 203ea3c7b..576b549c6 100644 --- a/google/cloud/bigquery/enums.py +++ b/google/cloud/bigquery/enums.py @@ -407,3 +407,22 @@ class BigLakeTableFormat(object): ICEBERG = "ICEBERG" """Apache Iceberg format.""" + + +class JobCreationMode(object): + """Documented values for Job Creation Mode.""" + + JOB_CREATION_MODE_UNSPECIFIED = "JOB_CREATION_MODE_UNSPECIFIED" + """Job creation mode is unspecified.""" + + JOB_CREATION_REQUIRED = "JOB_CREATION_REQUIRED" + """Job creation is always required.""" + + JOB_CREATION_OPTIONAL = "JOB_CREATION_OPTIONAL" + """Job creation is optional. + + Returning immediate results is prioritized. + BigQuery will automatically determine if a Job needs to be created. + The conditions under which BigQuery can decide to not create a Job are + subject to change. + """ diff --git a/samples/client_query_shortmode.py b/samples/client_query_job_optional.py similarity index 69% rename from samples/client_query_shortmode.py rename to samples/client_query_job_optional.py index 50446dc48..89e848867 100644 --- a/samples/client_query_shortmode.py +++ b/samples/client_query_job_optional.py @@ -13,16 +13,18 @@ # limitations under the License. -def client_query_shortmode() -> None: - # [START bigquery_query_shortquery] - # This example demonstrates issuing a query that may be run in short query mode. - # - # To enable the short query mode preview feature, the QUERY_PREVIEW_ENABLED - # environmental variable should be set to `TRUE`. +def client_query_job_optional() -> None: + # [START bigquery_query_job_optional] + # This example demonstrates executing a query without requiring an associated + # job. from google.cloud import bigquery + from google.cloud.bigquery.enums import JobCreationMode - # Construct a BigQuery client object. - client = bigquery.Client() + # Construct a BigQuery client object, specifying that the library should + # avoid creating jobs when possible. + client = bigquery.Client( + default_job_creation_mode=JobCreationMode.JOB_CREATION_OPTIONAL + ) query = """ SELECT @@ -44,10 +46,12 @@ def client_query_shortmode() -> None: if rows.job_id is not None: print("Query was run with job state. Job ID: {}".format(rows.job_id)) else: - print("Query was run in short mode. Query ID: {}".format(rows.query_id)) + print( + "Query was run without creating a job.. Query ID: {}".format(rows.query_id) + ) print("The query data:") for row in rows: # Row values can be accessed by field name or index. print("name={}, gender={}, total={}".format(row[0], row[1], row["total"])) - # [END bigquery_query_shortquery] + # [END bigquery_query_job_optional] diff --git a/samples/tests/test_client_query_shortmode.py b/samples/tests/test_client_query_job_optional.py similarity index 85% rename from samples/tests/test_client_query_shortmode.py rename to samples/tests/test_client_query_job_optional.py index 41132f24c..0e0b2cf19 100644 --- a/samples/tests/test_client_query_shortmode.py +++ b/samples/tests/test_client_query_job_optional.py @@ -1,4 +1,4 @@ -# Copyright 2024 Google LLC +# Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,13 +14,13 @@ import typing -from .. import client_query_shortmode +from .. import client_query_job_optional if typing.TYPE_CHECKING: import pytest def test_client_query_shortmode(capsys: "pytest.CaptureFixture[str]") -> None: - client_query_shortmode.client_query_shortmode() + client_query_job_optional.client_query_job_optional() out, err = capsys.readouterr() assert "Query was run" in out diff --git a/tests/unit/test__job_helpers.py b/tests/unit/test__job_helpers.py index 4fa093c69..dbebb01bb 100644 --- a/tests/unit/test__job_helpers.py +++ b/tests/unit/test__job_helpers.py @@ -554,13 +554,9 @@ def test_query_and_wait_retries_job_times_out(): ) -def test_query_and_wait_sets_job_creation_mode(monkeypatch: pytest.MonkeyPatch): - monkeypatch.setenv( - "QUERY_PREVIEW_ENABLED", - # The comparison should be case insensitive. - "TrUe", - ) +def test_query_and_wait_sets_job_creation_mode(): client = mock.create_autospec(Client) + client.default_job_creation_mode = "JOB_CREATION_OPTIONAL" client._call_api.return_value = { "jobReference": { "projectId": "response-project", @@ -605,6 +601,7 @@ def test_query_and_wait_sets_job_creation_mode(monkeypatch: pytest.MonkeyPatch): def test_query_and_wait_sets_location(): client = mock.create_autospec(Client) + client.default_job_creation_mode = None client._call_api.return_value = { "jobReference": { "projectId": "response-project", @@ -658,6 +655,7 @@ def test_query_and_wait_sets_location(): ) def test_query_and_wait_sets_max_results(max_results, page_size, expected): client = mock.create_autospec(Client) + client.default_job_creation_mode = None client._call_api.return_value = { "jobReference": { "projectId": "response-project", @@ -703,6 +701,7 @@ def test_query_and_wait_sets_max_results(max_results, page_size, expected): def test_query_and_wait_caches_completed_query_results_one_page(): client = mock.create_autospec(Client) + client.default_job_creation_mode = None client._call_api.return_value = { "jobReference": { "projectId": "response-project", @@ -768,6 +767,7 @@ def test_query_and_wait_caches_completed_query_results_one_page(): def test_query_and_wait_caches_completed_query_results_one_page_no_rows(): client = mock.create_autospec(Client) + client.default_job_creation_mode = None client._call_api.return_value = { "jobReference": { "projectId": "response-project", From edee9ddb1c138cce9874e47c684779ada85c4f32 Mon Sep 17 00:00:00 2001 From: Seth Hollyman Date: Mon, 19 May 2025 19:20:32 +0000 Subject: [PATCH 02/12] linting --- google/cloud/bigquery/_job_helpers.py | 1 - google/cloud/bigquery/enums.py | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/google/cloud/bigquery/_job_helpers.py b/google/cloud/bigquery/_job_helpers.py index ee2fc6be7..888dc1e73 100644 --- a/google/cloud/bigquery/_job_helpers.py +++ b/google/cloud/bigquery/_job_helpers.py @@ -37,7 +37,6 @@ import copy import functools -import os import uuid import textwrap from typing import Any, Dict, Optional, TYPE_CHECKING, Union diff --git a/google/cloud/bigquery/enums.py b/google/cloud/bigquery/enums.py index 576b549c6..4cb7a056d 100644 --- a/google/cloud/bigquery/enums.py +++ b/google/cloud/bigquery/enums.py @@ -419,8 +419,8 @@ class JobCreationMode(object): """Job creation is always required.""" JOB_CREATION_OPTIONAL = "JOB_CREATION_OPTIONAL" - """Job creation is optional. - + """Job creation is optional. + Returning immediate results is prioritized. BigQuery will automatically determine if a Job needs to be created. The conditions under which BigQuery can decide to not create a Job are From 698fdbbe0e469b0c5749e38afef7fabbb3c9ebc8 Mon Sep 17 00:00:00 2001 From: Seth Hollyman Date: Mon, 19 May 2025 19:30:56 +0000 Subject: [PATCH 03/12] switch to prop setter --- google/cloud/bigquery/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google/cloud/bigquery/client.py b/google/cloud/bigquery/client.py index 72546a1ff..aeccf6433 100644 --- a/google/cloud/bigquery/client.py +++ b/google/cloud/bigquery/client.py @@ -282,7 +282,7 @@ def __init__( self._connection = Connection(self, **kw_args) self._location = location self._default_load_job_config = copy.deepcopy(default_load_job_config) - self._default_job_creation_mode = default_job_creation_mode + self.default_job_creation_mode = default_job_creation_mode # Use property setter so validation can run. self.default_query_job_config = default_query_job_config From b300fb43939132c2eeeccb100779d78cd5b23b38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Swe=C3=B1a=20=28Swast=29?= Date: Fri, 23 May 2025 12:45:19 -0500 Subject: [PATCH 04/12] Update samples/client_query_job_optional.py Co-authored-by: Lingqing Gan --- samples/client_query_job_optional.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/client_query_job_optional.py b/samples/client_query_job_optional.py index 89e848867..6321aea35 100644 --- a/samples/client_query_job_optional.py +++ b/samples/client_query_job_optional.py @@ -47,7 +47,7 @@ def client_query_job_optional() -> None: print("Query was run with job state. Job ID: {}".format(rows.job_id)) else: print( - "Query was run without creating a job.. Query ID: {}".format(rows.query_id) + "Query was run without creating a job. Query ID: {}".format(rows.query_id) ) print("The query data:") From 289a933c7906d35ddd81775162e44b0b0af746e3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 21 May 2025 16:20:17 +0200 Subject: [PATCH 05/12] fix(deps): update all dependencies (#2184) * fix(deps): update all dependencies * Update pyproject.toml * Update .github/workflows/docs.yml * Update .github/workflows/docs.yml --------- Co-authored-by: Chalmer Lowe --- samples/desktopapp/requirements-test.txt | 2 +- samples/desktopapp/requirements.txt | 2 +- samples/geography/requirements.txt | 6 +++--- samples/magics/requirements-test.txt | 2 +- samples/magics/requirements.txt | 4 ++-- samples/notebooks/requirements-test.txt | 2 +- samples/notebooks/requirements.txt | 4 ++-- samples/snippets/requirements-test.txt | 2 +- samples/snippets/requirements.txt | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/samples/desktopapp/requirements-test.txt b/samples/desktopapp/requirements-test.txt index 6abea3b4d..cc71ee426 100644 --- a/samples/desktopapp/requirements-test.txt +++ b/samples/desktopapp/requirements-test.txt @@ -1,4 +1,4 @@ -google-cloud-testutils==1.6.2 +google-cloud-testutils==1.6.4 pytest==8.3.5 mock==5.2.0 pytest-xdist==3.6.1 diff --git a/samples/desktopapp/requirements.txt b/samples/desktopapp/requirements.txt index 743d0fe35..4a5b75346 100644 --- a/samples/desktopapp/requirements.txt +++ b/samples/desktopapp/requirements.txt @@ -1,2 +1,2 @@ -google-cloud-bigquery==3.32.0 +google-cloud-bigquery==3.33.0 google-auth-oauthlib==1.2.2 diff --git a/samples/geography/requirements.txt b/samples/geography/requirements.txt index 434a594cb..3b1a3ef54 100644 --- a/samples/geography/requirements.txt +++ b/samples/geography/requirements.txt @@ -3,7 +3,7 @@ certifi==2025.4.26 cffi==1.17.1 charset-normalizer==3.4.2 click===8.1.8; python_version == '3.9' -click==8.2.0; python_version >= '3.10' +click==8.2.1; python_version >= '3.10' click-plugins==1.1.1 cligj==0.7.2 db-dtypes==1.4.3 @@ -12,7 +12,7 @@ geojson==3.2.0 geopandas==1.0.1 google-api-core==2.24.2 google-auth==2.40.1 -google-cloud-bigquery==3.32.0 +google-cloud-bigquery==3.33.0 google-cloud-bigquery-storage==2.31.0 google-cloud-core==2.4.3 google-crc32c==1.7.1 @@ -36,7 +36,7 @@ PyYAML==6.0.2 requests==2.32.3 rsa==4.9.1 Shapely===2.0.7; python_version == '3.9' -Shapely==2.1.0; python_version >= '3.10' +Shapely==2.1.1; python_version >= '3.10' six==1.17.0 typing-extensions==4.13.2 typing-inspect==0.9.0 diff --git a/samples/magics/requirements-test.txt b/samples/magics/requirements-test.txt index 6abea3b4d..cc71ee426 100644 --- a/samples/magics/requirements-test.txt +++ b/samples/magics/requirements-test.txt @@ -1,4 +1,4 @@ -google-cloud-testutils==1.6.2 +google-cloud-testutils==1.6.4 pytest==8.3.5 mock==5.2.0 pytest-xdist==3.6.1 diff --git a/samples/magics/requirements.txt b/samples/magics/requirements.txt index bb60f2a67..7d0c91e3d 100644 --- a/samples/magics/requirements.txt +++ b/samples/magics/requirements.txt @@ -1,6 +1,6 @@ -bigquery_magics==0.9.0 +bigquery_magics==0.10.0 db-dtypes==1.4.3 -google.cloud.bigquery==3.32.0 +google.cloud.bigquery==3.33.0 google-cloud-bigquery-storage==2.31.0 ipython===8.18.1 pandas==2.2.3 diff --git a/samples/notebooks/requirements-test.txt b/samples/notebooks/requirements-test.txt index 6abea3b4d..cc71ee426 100644 --- a/samples/notebooks/requirements-test.txt +++ b/samples/notebooks/requirements-test.txt @@ -1,4 +1,4 @@ -google-cloud-testutils==1.6.2 +google-cloud-testutils==1.6.4 pytest==8.3.5 mock==5.2.0 pytest-xdist==3.6.1 diff --git a/samples/notebooks/requirements.txt b/samples/notebooks/requirements.txt index 17f43bf78..9f131e5b8 100644 --- a/samples/notebooks/requirements.txt +++ b/samples/notebooks/requirements.txt @@ -1,6 +1,6 @@ -bigquery-magics==0.9.0 +bigquery-magics==0.10.0 db-dtypes==1.4.3 -google-cloud-bigquery==3.32.0 +google-cloud-bigquery==3.33.0 google-cloud-bigquery-storage==2.31.0 ipython===8.18.1; python_version == '3.9' ipython==9.2.0; python_version >= '3.10' diff --git a/samples/snippets/requirements-test.txt b/samples/snippets/requirements-test.txt index 6760e1228..503324cb0 100644 --- a/samples/snippets/requirements-test.txt +++ b/samples/snippets/requirements-test.txt @@ -1,5 +1,5 @@ # samples/snippets should be runnable with no "extras" -google-cloud-testutils==1.6.2 +google-cloud-testutils==1.6.4 pytest==8.3.5 mock==5.2.0 pytest-xdist==3.6.1 diff --git a/samples/snippets/requirements.txt b/samples/snippets/requirements.txt index c31815d69..dae43eff3 100644 --- a/samples/snippets/requirements.txt +++ b/samples/snippets/requirements.txt @@ -1,2 +1,2 @@ # samples/snippets should be runnable with no "extras" -google-cloud-bigquery==3.32.0 +google-cloud-bigquery==3.33.0 From 7043686341a6593ef9b1925232ba5ebb5feb175b Mon Sep 17 00:00:00 2001 From: Chalmer Lowe Date: Thu, 22 May 2025 13:01:13 -0400 Subject: [PATCH 06/12] ddocs: fixes several typos and updates a try except block (#2197) --- google/cloud/bigquery/_helpers.py | 2 +- google/cloud/bigquery/_pandas_helpers.py | 2 +- google/cloud/bigquery/client.py | 2 +- google/cloud/bigquery/table.py | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/google/cloud/bigquery/_helpers.py b/google/cloud/bigquery/_helpers.py index 76c4f1fbd..c7d7705e0 100644 --- a/google/cloud/bigquery/_helpers.py +++ b/google/cloud/bigquery/_helpers.py @@ -388,7 +388,7 @@ def range_to_py(self, value, field): class DataFrameCellDataParser(CellDataParser): - """Override of CellDataParser to handle differences in expection of values in DataFrame-like outputs. + """Override of CellDataParser to handle differences in expression of values in DataFrame-like outputs. This is used to turn the output of the REST API into a pyarrow Table, emulating the serialized arrow from the BigQuery Storage Read API. diff --git a/google/cloud/bigquery/_pandas_helpers.py b/google/cloud/bigquery/_pandas_helpers.py index 6691e7ef6..10a5c59bb 100644 --- a/google/cloud/bigquery/_pandas_helpers.py +++ b/google/cloud/bigquery/_pandas_helpers.py @@ -1144,7 +1144,7 @@ def determine_requested_streams( """ if preserve_order: - # If preserve order is set, it takes precendence. + # If preserve order is set, it takes precedence. # Limit the requested streams to 1, to ensure that order # is preserved) return 1 diff --git a/google/cloud/bigquery/client.py b/google/cloud/bigquery/client.py index aeccf6433..c6873545b 100644 --- a/google/cloud/bigquery/client.py +++ b/google/cloud/bigquery/client.py @@ -4142,7 +4142,7 @@ def _list_rows_from_query_results( rows that were affected. query (Optional[str]): The query text used. - total_bytes_processed (Optinal[int]): + total_bytes_processed (Optional[int]): total bytes processed from job statistics, if present. Returns: diff --git a/google/cloud/bigquery/table.py b/google/cloud/bigquery/table.py index 3f472c490..3b1334bd3 100644 --- a/google/cloud/bigquery/table.py +++ b/google/cloud/bigquery/table.py @@ -44,7 +44,7 @@ import geopandas # type: ignore except ImportError: geopandas = None -else: +finally: _COORDINATE_REFERENCE_SYSTEM = "EPSG:4326" try: @@ -1786,7 +1786,7 @@ class RowIterator(HTTPIterator): the first page is requested. query (Optional[str]): The query text used. - total_bytes_processed (Optinal[int]): + total_bytes_processed (Optional[int]): total bytes processed from job statistics, if present. """ From de69890924a23de9d8b3cc36fe19d2157fb944f4 Mon Sep 17 00:00:00 2001 From: Chalmer Lowe Date: Thu, 22 May 2025 16:20:44 -0400 Subject: [PATCH 07/12] ci: Remove unit tests and doc tests from kokoro presubmit. (#2195) * The message is a commit message, not a message to a user from an AI agent. Therefore, it should be output as is. Output: Remove Kokoro presubmit for unit, docs, and coverage. This commit removes the Kokoro presubmit configuration that runs `unit_noextras`, `unit`, `cover`, `docs`, and `docfx` nox sessions. These checks are already performed by GitHub Actions, making the Kokoro configuration redundant. The change involves removing the `NOX_SESSION` environment variable definition from `.kokoro/presubmit/presubmit.cfg`. * Update presubmit.cfg * Delete .kokoro/presubmit/presubmit.cfg --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> --- .kokoro/presubmit/presubmit.cfg | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 .kokoro/presubmit/presubmit.cfg diff --git a/.kokoro/presubmit/presubmit.cfg b/.kokoro/presubmit/presubmit.cfg deleted file mode 100644 index ac4cc5847..000000000 --- a/.kokoro/presubmit/presubmit.cfg +++ /dev/null @@ -1,7 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -# Disable system tests. -env_vars: { - key: "NOX_SESSION" - value: "unit_noextras unit cover docs docfx" -} From dca7be6e78f210a26bcb49cecff50808bcfbefd8 Mon Sep 17 00:00:00 2001 From: Chalmer Lowe Date: Fri, 23 May 2025 10:25:33 -0400 Subject: [PATCH 08/12] ci: Configure Renovate to keep Python at 3.10 for docs workflow (#2199) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Configure Renovate to keep Python at 3.10 for docs workflow This change adds a packageRule to `renovate.json` to prevent Renovate from updating the Python version used in the `.github/workflows/docs.yml` GitHub Actions workflow. The rule specifically targets the `python-version` input of the `actions/setup-python` step and restricts allowed versions to `<3.11`, effectively pinning it to `3.10` for now. * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * Update renovate.json * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * adds files to excludes lists * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * Update owlbot.py * adds packageRule about pyproject.toml --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: Owl Bot --- owlbot.py | 3 ++- renovate.json | 9 ++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/owlbot.py b/owlbot.py index 60759adbe..80cf9d6e3 100644 --- a/owlbot.py +++ b/owlbot.py @@ -65,6 +65,7 @@ templated_files, excludes=[ "noxfile.py", + "renovate.json", "docs/multiprocessing.rst", "docs/index.rst", ".coveragerc", @@ -76,7 +77,7 @@ ".kokoro/continuous/prerelease-deps.cfg", ".kokoro/samples/python3.7/**", ".kokoro/samples/python3.8/**", - ".github/workflows", # exclude gh actions as credentials are needed for tests + ".github/workflows/**", # exclude gh actions as credentials are needed for tests "README.rst", ], ) diff --git a/renovate.json b/renovate.json index c7875c469..51eb51d6e 100644 --- a/renovate.json +++ b/renovate.json @@ -8,5 +8,12 @@ "ignorePaths": [".pre-commit-config.yaml", ".kokoro/requirements.txt", "setup.py", ".github/workflows/unittest.yml"], "pip_requirements": { "fileMatch": ["requirements-test.txt", "samples/[\\S/]*constraints.txt", "samples/[\\S/]*constraints-test.txt"] - } + }, + "packageRules": [ + { + "matchFileNames": ["pyproject.toml"], + "matchStrings": ["matplotlib (.*); python_version == '3.9'"], + "allowedVersions": ">= 3.7.1, <= 3.9.2" + } + ] } From 28b69cfaff6f08dc8f79c57a61cc335811958ad1 Mon Sep 17 00:00:00 2001 From: Chalmer Lowe Date: Fri, 23 May 2025 10:57:55 -0400 Subject: [PATCH 09/12] ci: updates renovate.json to ignore docs.yml (#2200) * updates renovate to ignore docs.yml * Update renovate.json --- renovate.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/renovate.json b/renovate.json index 51eb51d6e..3ea143d4c 100644 --- a/renovate.json +++ b/renovate.json @@ -5,7 +5,7 @@ ":preserveSemverRanges", ":disableDependencyDashboard" ], - "ignorePaths": [".pre-commit-config.yaml", ".kokoro/requirements.txt", "setup.py", ".github/workflows/unittest.yml"], + "ignorePaths": [".pre-commit-config.yaml", ".kokoro/requirements.txt", "setup.py", ".github/workflows/unittest.yml", ".github/workflows/docs.yml"], "pip_requirements": { "fileMatch": ["requirements-test.txt", "samples/[\\S/]*constraints.txt", "samples/[\\S/]*constraints-test.txt"] }, From afa142c9efff67a7be2b631f880bf0e79c8995ab Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 23 May 2025 17:32:50 +0200 Subject: [PATCH 10/12] chore(deps): update dependency google-auth to v2.40.2 (#2196) --- samples/geography/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/geography/requirements.txt b/samples/geography/requirements.txt index 3b1a3ef54..7a0946fae 100644 --- a/samples/geography/requirements.txt +++ b/samples/geography/requirements.txt @@ -11,7 +11,7 @@ Fiona==1.10.1 geojson==3.2.0 geopandas==1.0.1 google-api-core==2.24.2 -google-auth==2.40.1 +google-auth==2.40.2 google-cloud-bigquery==3.33.0 google-cloud-bigquery-storage==2.31.0 google-cloud-core==2.4.3 From 4ab55c6e9b71615fd9dbd102d49a7b196c354a46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Swe=C3=B1a=20=28Swast=29?= Date: Tue, 27 May 2025 04:38:22 -0500 Subject: [PATCH 11/12] docs: use query_and_wait in the array parameters sample (#2202) --- samples/client_query_w_array_params.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/client_query_w_array_params.py b/samples/client_query_w_array_params.py index 25592a94a..e9d759f61 100644 --- a/samples/client_query_w_array_params.py +++ b/samples/client_query_w_array_params.py @@ -35,8 +35,8 @@ def client_query_w_array_params() -> None: bigquery.ArrayQueryParameter("states", "STRING", ["WA", "WI", "WV", "WY"]), ] ) - query_job = client.query(query, job_config=job_config) # Make an API request. + rows = client.query_and_wait(query, job_config=job_config) # Make an API request. - for row in query_job: + for row in rows: print("{}: \t{}".format(row.name, row.count)) # [END bigquery_query_params_arrays] From ca36518b302c2dc1864401e7c44b7b08d6ad7025 Mon Sep 17 00:00:00 2001 From: Seth Hollyman Date: Tue, 27 May 2025 16:45:06 +0000 Subject: [PATCH 12/12] address reviewer feedback --- tests/unit/test__job_helpers.py | 2 +- tests/unit/test_client.py | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/unit/test__job_helpers.py b/tests/unit/test__job_helpers.py index dbebb01bb..417f911b8 100644 --- a/tests/unit/test__job_helpers.py +++ b/tests/unit/test__job_helpers.py @@ -601,7 +601,6 @@ def test_query_and_wait_sets_job_creation_mode(): def test_query_and_wait_sets_location(): client = mock.create_autospec(Client) - client.default_job_creation_mode = None client._call_api.return_value = { "jobReference": { "projectId": "response-project", @@ -639,6 +638,7 @@ def test_query_and_wait_sets_location(): "useInt64Timestamp": True, }, "requestId": mock.ANY, + "jobCreationMode": mock.ANY, }, timeout=None, ) diff --git a/tests/unit/test_client.py b/tests/unit/test_client.py index 468068321..8ce8d2cbd 100644 --- a/tests/unit/test_client.py +++ b/tests/unit/test_client.py @@ -213,6 +213,17 @@ def test_ctor_w_client_options_universe(self): ) self.assertEqual(client._connection.API_BASE_URL, "https://bigquery.foo.com") + def test_ctor_w_job_creation_mode(self): + creds = _make_credentials() + http = object() + client = self._make_one( + project=self.PROJECT, + credentials=creds, + _http=http, + default_job_creation_mode="foo", + ) + self.assertEqual(client.default_job_creation_mode, "foo") + def test_ctor_w_location(self): from google.cloud.bigquery._http import Connection