From 44ce8617ac757f6bb67a4654ae588e767ad7dddd Mon Sep 17 00:00:00 2001 From: chalmer lowe Date: Fri, 14 Nov 2025 13:38:25 -0500 Subject: [PATCH 01/12] chore(python): Add support for Python 3.14 --- owlbot.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/owlbot.py b/owlbot.py index 4547c4d2d0..764d06632e 100644 --- a/owlbot.py +++ b/owlbot.py @@ -272,7 +272,8 @@ def get_staging_dirs( cov_level=98, split_system_tests=True, system_test_extras=["tracing"], - system_test_python_versions=["3.12"] + system_test_python_versions=["3.12"], + unit_test_python_versions=["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] ) s.move( templated_files, @@ -302,6 +303,12 @@ def get_staging_dirs( # Update samples folder in CONTRIBUTING.rst s.replace("CONTRIBUTING.rst", "samples/snippets", "samples/samples") +s.replace( + "noxfile.py", + '''session.python in \("3.11", "3.12", "3.13"\)''', + '''session.python in ("3.11", "3.12", "3.13", "3.14")''' +) + # ---------------------------------------------------------------------------- # Samples templates # ---------------------------------------------------------------------------- From 60c01846782453ef5c1d72177c478a8a39647e89 Mon Sep 17 00:00:00 2001 From: Owl Bot Date: Fri, 14 Nov 2025 18:41:44 +0000 Subject: [PATCH 02/12] =?UTF-8?q?=F0=9F=A6=89=20Updates=20from=20OwlBot=20?= =?UTF-8?q?post-processor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --- noxfile.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/noxfile.py b/noxfile.py index b101f46b2e..9f770ab13f 100644 --- a/noxfile.py +++ b/noxfile.py @@ -195,7 +195,12 @@ def install_unittest_dependencies(session, *constraints): def unit(session, protobuf_implementation): # Install all test dependencies, then install this package in-place. - if protobuf_implementation == "cpp" and session.python in ("3.11", "3.12", "3.13"): + if protobuf_implementation == "cpp" and session.python in ( + "3.11", + "3.12", + "3.13", + "3.14", + ): session.skip("cpp implementation is not supported in python 3.11+") constraints_path = str( @@ -326,7 +331,12 @@ def system(session, protobuf_implementation, database_dialect): "Only run system tests on real Spanner with one protobuf implementation to speed up the build" ) - if protobuf_implementation == "cpp" and session.python in ("3.11", "3.12", "3.13"): + if protobuf_implementation == "cpp" and session.python in ( + "3.11", + "3.12", + "3.13", + "3.14", + ): session.skip("cpp implementation is not supported in python 3.11+") # Install pyopenssl for mTLS testing. @@ -485,7 +495,12 @@ def docfx(session): def prerelease_deps(session, protobuf_implementation, database_dialect): """Run all tests with prerelease versions of dependencies installed.""" - if protobuf_implementation == "cpp" and session.python in ("3.11", "3.12", "3.13"): + if protobuf_implementation == "cpp" and session.python in ( + "3.11", + "3.12", + "3.13", + "3.14", + ): session.skip("cpp implementation is not supported in python 3.11+") # Install all dependencies From 6cad111d90add0e69a44ea778d1810f4ba5d5005 Mon Sep 17 00:00:00 2001 From: chalmer lowe Date: Mon, 17 Nov 2025 07:22:34 -0500 Subject: [PATCH 03/12] chore(python): Update core files for Python 3.14 support --- CONTRIBUTING.rst | 2 ++ noxfile.py | 8 +++++--- setup.py | 1 + testing/constraints-3.14.txt | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 76e9061cd2..60be7c4f93 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -226,12 +226,14 @@ We support: - `Python 3.11`_ - `Python 3.12`_ - `Python 3.13`_ +- `Python 3.14`_ .. _Python 3.9: https://docs.python.org/3.9/ .. _Python 3.10: https://docs.python.org/3.10/ .. _Python 3.11: https://docs.python.org/3.11/ .. _Python 3.12: https://docs.python.org/3.12/ .. _Python 3.13: https://docs.python.org/3.13/ +.. _Python 3.14: https://docs.python.org/3.14/ Supported versions can be found in our ``noxfile.py`` `config`_. diff --git a/noxfile.py b/noxfile.py index 9f770ab13f..5fba75e211 100644 --- a/noxfile.py +++ b/noxfile.py @@ -32,10 +32,10 @@ ISORT_VERSION = "isort==5.11.0" LINT_PATHS = ["docs", "google", "tests", "noxfile.py", "setup.py"] -DEFAULT_PYTHON_VERSION = "3.12" +DEFAULT_PYTHON_VERSION = "3.14" DEFAULT_MOCK_SERVER_TESTS_PYTHON_VERSION = "3.12" -SYSTEM_TEST_PYTHON_VERSIONS: List[str] = ["3.12"] +SYSTEM_TEST_PYTHON_VERSIONS: List[str] = ["3.14"] UNIT_TEST_PYTHON_VERSIONS: List[str] = [ "3.9", @@ -43,6 +43,7 @@ "3.11", "3.12", "3.13", + "3.14", ] UNIT_TEST_STANDARD_DEPENDENCIES = [ "mock", @@ -81,6 +82,7 @@ "unit-3.11", "unit-3.12", "unit-3.13", + "unit-3.14", "system", "cover", "lint", @@ -480,7 +482,7 @@ def docfx(session): ) -@nox.session(python="3.13") +@nox.session(python="3.14") @nox.parametrize( "protobuf_implementation,database_dialect", [ diff --git a/setup.py b/setup.py index 216b095d0b..fdd911bfd1 100644 --- a/setup.py +++ b/setup.py @@ -87,6 +87,7 @@ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.14", "Operating System :: OS Independent", "Topic :: Internet", ], diff --git a/testing/constraints-3.14.txt b/testing/constraints-3.14.txt index 2ae5a677e8..92054fc895 100644 --- a/testing/constraints-3.14.txt +++ b/testing/constraints-3.14.txt @@ -10,4 +10,4 @@ google-auth>=2 grpcio>=1 proto-plus>=1 protobuf>=6 -grpc-google-iam-v1>=0 +grpc-google-iam-v1>=0 \ No newline at end of file From 7be3ae7839a57aed1365759fdaed6770cfe2f5cd Mon Sep 17 00:00:00 2001 From: chalmer lowe Date: Mon, 17 Nov 2025 07:23:35 -0500 Subject: [PATCH 04/12] chore(python): Update sync-repo-settings.yaml for Python 3.14 --- .github/sync-repo-settings.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/sync-repo-settings.yaml b/.github/sync-repo-settings.yaml index d726d1193d..ce930afcd6 100644 --- a/.github/sync-repo-settings.yaml +++ b/.github/sync-repo-settings.yaml @@ -8,8 +8,8 @@ branchProtectionRules: requiresStrictStatusChecks: true requiredStatusCheckContexts: - 'Kokoro' - - 'Kokoro system-3.12' + - 'Kokoro system-3.14' - 'cla/google' - 'Samples - Lint' - 'Samples - Python 3.9' - - 'Samples - Python 3.12' + - 'Samples - Python 3.14' From fa221258cbea91361bb1c4a3078f89532f8f0d7e Mon Sep 17 00:00:00 2001 From: chalmer lowe Date: Mon, 17 Nov 2025 09:17:39 -0500 Subject: [PATCH 05/12] chore(ci): Update Python versions in presubmit.yaml to include 3.14 --- .github/workflows/presubmit.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/presubmit.yaml b/.github/workflows/presubmit.yaml index 67db6136d1..56386a746c 100644 --- a/.github/workflows/presubmit.yaml +++ b/.github/workflows/presubmit.yaml @@ -17,7 +17,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v6 with: - python-version: 3.13 + python-version: 3.14 - name: Install nox run: python -m pip install nox - name: Check formatting @@ -27,7 +27,7 @@ jobs: strategy: fail-fast: false matrix: - python: ["3.9", "3.10", "3.11", "3.12", "3.13"] + python: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] steps: - name: Checkout code From 2ac30b684ddcdd11b6eed12b7831d99208513198 Mon Sep 17 00:00:00 2001 From: chalmer lowe Date: Mon, 17 Nov 2025 09:35:52 -0500 Subject: [PATCH 06/12] chore(ci): Update Python version to 3.14 in remaining workflows --- ...integration-tests-against-emulator-with-regular-session.yaml | 2 +- .github/workflows/integration-tests-against-emulator.yaml | 2 +- .github/workflows/mock_server_tests.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/integration-tests-against-emulator-with-regular-session.yaml b/.github/workflows/integration-tests-against-emulator-with-regular-session.yaml index 826a3b7629..3f2d3b7ba2 100644 --- a/.github/workflows/integration-tests-against-emulator-with-regular-session.yaml +++ b/.github/workflows/integration-tests-against-emulator-with-regular-session.yaml @@ -21,7 +21,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v6 with: - python-version: 3.13 + python-version: 3.14 - name: Install nox run: python -m pip install nox - name: Run system tests diff --git a/.github/workflows/integration-tests-against-emulator.yaml b/.github/workflows/integration-tests-against-emulator.yaml index e7158307b8..e8078107bc 100644 --- a/.github/workflows/integration-tests-against-emulator.yaml +++ b/.github/workflows/integration-tests-against-emulator.yaml @@ -21,7 +21,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v6 with: - python-version: 3.13 + python-version: 3.14 - name: Install nox run: python -m pip install nox - name: Run system tests diff --git a/.github/workflows/mock_server_tests.yaml b/.github/workflows/mock_server_tests.yaml index b705c98191..d16feac517 100644 --- a/.github/workflows/mock_server_tests.yaml +++ b/.github/workflows/mock_server_tests.yaml @@ -14,7 +14,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v6 with: - python-version: 3.13 + python-version: 3.14 - name: Install nox run: python -m pip install nox - name: Run mock server tests From 446cc466b89bcd96444e901e85dd304852a7f12e Mon Sep 17 00:00:00 2001 From: chalmer lowe Date: Mon, 17 Nov 2025 10:40:21 -0500 Subject: [PATCH 07/12] sending debug content to compare remote test results to local tests results, will revert --- noxfile.py | 2 +- tests/unit/test_spanner.py | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/noxfile.py b/noxfile.py index 5fba75e211..67d807b1c2 100644 --- a/noxfile.py +++ b/noxfile.py @@ -227,7 +227,7 @@ def unit(session, protobuf_implementation): "--cov-config=.coveragerc", "--cov-report=", "--cov-fail-under=0", - os.path.join("tests", "unit"), + #os.path.join("tests", "unit"), *session.posargs, env={ "PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION": protobuf_implementation, diff --git a/tests/unit/test_spanner.py b/tests/unit/test_spanner.py index e35b817858..05d57bb412 100644 --- a/tests/unit/test_spanner.py +++ b/tests/unit/test_spanner.py @@ -1071,6 +1071,38 @@ def test_transaction_for_concurrent_statement_should_begin_one_transaction_with_ ) self.assertEqual(api.execute_batch_dml.call_count, 2) + a = mock.call( + request=self._batch_update_expected_request(), + metadata=[ + ("google-cloud-resource-prefix", database.name), + ("x-goog-spanner-route-to-leader", "true"), + ( + "x-goog-spanner-request-id", + f"1.{REQ_RAND_PROCESS_ID}.{database._nth_client_id}.{database._channel_id}.1.1", + ), + ], + retry=RETRY, + timeout=TIMEOUT, + ) + b = mock.call( + request=self._batch_update_expected_request(begin=False), + metadata=[ + ("google-cloud-resource-prefix", database.name), + ("x-goog-spanner-route-to-leader", "true"), + ( + "x-goog-spanner-request-id", + f"1.{REQ_RAND_PROCESS_ID}.{database._nth_client_id}.{database._channel_id}.2.1", + ), + ], + retry=RETRY, + timeout=TIMEOUT, + ) + print("A: ", a) + print("B: ", b) + + + + self.assertEqual( api.execute_batch_dml.call_args_list, [ From 0c26efcaa83b5aee12979a79014afa53a11977b1 Mon Sep 17 00:00:00 2001 From: Owl Bot Date: Mon, 17 Nov 2025 15:42:31 +0000 Subject: [PATCH 08/12] =?UTF-8?q?=F0=9F=A6=89=20Updates=20from=20OwlBot=20?= =?UTF-8?q?post-processor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --- noxfile.py | 2 +- tests/unit/test_spanner.py | 53 ++++++++++++++++++-------------------- 2 files changed, 26 insertions(+), 29 deletions(-) diff --git a/noxfile.py b/noxfile.py index 67d807b1c2..b9ad3429f7 100644 --- a/noxfile.py +++ b/noxfile.py @@ -227,7 +227,7 @@ def unit(session, protobuf_implementation): "--cov-config=.coveragerc", "--cov-report=", "--cov-fail-under=0", - #os.path.join("tests", "unit"), + # os.path.join("tests", "unit"), *session.posargs, env={ "PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION": protobuf_implementation, diff --git a/tests/unit/test_spanner.py b/tests/unit/test_spanner.py index 05d57bb412..ac57500b18 100644 --- a/tests/unit/test_spanner.py +++ b/tests/unit/test_spanner.py @@ -1072,37 +1072,34 @@ def test_transaction_for_concurrent_statement_should_begin_one_transaction_with_ self.assertEqual(api.execute_batch_dml.call_count, 2) a = mock.call( - request=self._batch_update_expected_request(), - metadata=[ - ("google-cloud-resource-prefix", database.name), - ("x-goog-spanner-route-to-leader", "true"), - ( - "x-goog-spanner-request-id", - f"1.{REQ_RAND_PROCESS_ID}.{database._nth_client_id}.{database._channel_id}.1.1", - ), - ], - retry=RETRY, - timeout=TIMEOUT, - ) + request=self._batch_update_expected_request(), + metadata=[ + ("google-cloud-resource-prefix", database.name), + ("x-goog-spanner-route-to-leader", "true"), + ( + "x-goog-spanner-request-id", + f"1.{REQ_RAND_PROCESS_ID}.{database._nth_client_id}.{database._channel_id}.1.1", + ), + ], + retry=RETRY, + timeout=TIMEOUT, + ) b = mock.call( - request=self._batch_update_expected_request(begin=False), - metadata=[ - ("google-cloud-resource-prefix", database.name), - ("x-goog-spanner-route-to-leader", "true"), - ( - "x-goog-spanner-request-id", - f"1.{REQ_RAND_PROCESS_ID}.{database._nth_client_id}.{database._channel_id}.2.1", - ), - ], - retry=RETRY, - timeout=TIMEOUT, - ) + request=self._batch_update_expected_request(begin=False), + metadata=[ + ("google-cloud-resource-prefix", database.name), + ("x-goog-spanner-route-to-leader", "true"), + ( + "x-goog-spanner-request-id", + f"1.{REQ_RAND_PROCESS_ID}.{database._nth_client_id}.{database._channel_id}.2.1", + ), + ], + retry=RETRY, + timeout=TIMEOUT, + ) print("A: ", a) print("B: ", b) - - - - + self.assertEqual( api.execute_batch_dml.call_args_list, [ From f8365289696f65be49b2abb7e14638ec6a8f46fe Mon Sep 17 00:00:00 2001 From: Chalmer Lowe Date: Mon, 17 Nov 2025 11:16:01 -0500 Subject: [PATCH 09/12] Apply suggestion from @chalmerlowe --- noxfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noxfile.py b/noxfile.py index b9ad3429f7..5fba75e211 100644 --- a/noxfile.py +++ b/noxfile.py @@ -227,7 +227,7 @@ def unit(session, protobuf_implementation): "--cov-config=.coveragerc", "--cov-report=", "--cov-fail-under=0", - # os.path.join("tests", "unit"), + os.path.join("tests", "unit"), *session.posargs, env={ "PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION": protobuf_implementation, From 43a929494d861df660bfccc51f8fd40c79c99428 Mon Sep 17 00:00:00 2001 From: chalmer lowe Date: Mon, 17 Nov 2025 11:18:06 -0500 Subject: [PATCH 10/12] adds -s flag in the hopes of enabling debugging in remote repo --- noxfile.py | 1 + 1 file changed, 1 insertion(+) diff --git a/noxfile.py b/noxfile.py index 5fba75e211..51a1e3aeb4 100644 --- a/noxfile.py +++ b/noxfile.py @@ -220,6 +220,7 @@ def unit(session, protobuf_implementation): session.run( "py.test", "--quiet", + "-s", f"--junitxml=unit_{session.python}_sponge_log.xml", "--cov=google", "--cov=tests/unit", From cf8bf6451ea7dc010883d992afa0111a73d672e5 Mon Sep 17 00:00:00 2001 From: chalmer lowe Date: Mon, 17 Nov 2025 12:00:14 -0500 Subject: [PATCH 11/12] sending debug content to compare remote test results to local tests results, will revert part II --- tests/unit/test_spanner.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/unit/test_spanner.py b/tests/unit/test_spanner.py index ac57500b18..382efa0922 100644 --- a/tests/unit/test_spanner.py +++ b/tests/unit/test_spanner.py @@ -1071,7 +1071,10 @@ def test_transaction_for_concurrent_statement_should_begin_one_transaction_with_ ) self.assertEqual(api.execute_batch_dml.call_count, 2) - a = mock.call( + + call_args_list = api.execute_batch_dml.call_args_list + + a11 = mock.call( request=self._batch_update_expected_request(), metadata=[ ("google-cloud-resource-prefix", database.name), @@ -1084,7 +1087,7 @@ def test_transaction_for_concurrent_statement_should_begin_one_transaction_with_ retry=RETRY, timeout=TIMEOUT, ) - b = mock.call( + b21 = mock.call( request=self._batch_update_expected_request(begin=False), metadata=[ ("google-cloud-resource-prefix", database.name), @@ -1097,8 +1100,8 @@ def test_transaction_for_concurrent_statement_should_begin_one_transaction_with_ retry=RETRY, timeout=TIMEOUT, ) - print("A: ", a) - print("B: ", b) + print("\nDINOSAUR CALL_ARGS_LIST: ", call_args_list) + print("\nDINOSAUR BOTH: ", [a11, b21]) self.assertEqual( api.execute_batch_dml.call_args_list, From 051f30f65b9a7403abe8d2364f1c5675009488ef Mon Sep 17 00:00:00 2001 From: Owl Bot Date: Mon, 17 Nov 2025 17:02:36 +0000 Subject: [PATCH 12/12] =?UTF-8?q?=F0=9F=A6=89=20Updates=20from=20OwlBot=20?= =?UTF-8?q?post-processor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --- tests/unit/test_spanner.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/test_spanner.py b/tests/unit/test_spanner.py index 382efa0922..caa143d418 100644 --- a/tests/unit/test_spanner.py +++ b/tests/unit/test_spanner.py @@ -1071,9 +1071,9 @@ def test_transaction_for_concurrent_statement_should_begin_one_transaction_with_ ) self.assertEqual(api.execute_batch_dml.call_count, 2) - + call_args_list = api.execute_batch_dml.call_args_list - + a11 = mock.call( request=self._batch_update_expected_request(), metadata=[