From 0dd656a308d6a04f23843d7a639267dff00d533d Mon Sep 17 00:00:00 2001 From: rahul yadav Date: Wed, 6 Aug 2025 11:35:52 +0530 Subject: [PATCH 1/6] deps: Remove Python 3.7 and 3.8 as supported runtimes --- .github/workflows/presubmit.yaml | 4 +-- .kokoro/samples/python3.7/common.cfg | 40 --------------------- .kokoro/samples/python3.7/continuous.cfg | 6 ---- .kokoro/samples/python3.7/periodic-head.cfg | 11 ------ .kokoro/samples/python3.7/periodic.cfg | 6 ---- .kokoro/samples/python3.7/presubmit.cfg | 6 ---- .kokoro/samples/python3.8/common.cfg | 40 --------------------- .kokoro/samples/python3.8/continuous.cfg | 6 ---- .kokoro/samples/python3.8/periodic-head.cfg | 11 ------ .kokoro/samples/python3.8/periodic.cfg | 6 ---- .kokoro/samples/python3.8/presubmit.cfg | 6 ---- CONTRIBUTING.rst | 16 ++++----- README.rst | 5 +-- noxfile.py | 4 --- owlbot.py | 13 +++++++ samples/samples/noxfile.py | 2 +- setup.py | 4 +-- testing/constraints-3.7.txt | 20 ----------- testing/constraints-3.8.txt | 7 ---- 19 files changed, 26 insertions(+), 187 deletions(-) delete mode 100644 .kokoro/samples/python3.7/common.cfg delete mode 100644 .kokoro/samples/python3.7/continuous.cfg delete mode 100644 .kokoro/samples/python3.7/periodic-head.cfg delete mode 100644 .kokoro/samples/python3.7/periodic.cfg delete mode 100644 .kokoro/samples/python3.7/presubmit.cfg delete mode 100644 .kokoro/samples/python3.8/common.cfg delete mode 100644 .kokoro/samples/python3.8/continuous.cfg delete mode 100644 .kokoro/samples/python3.8/periodic-head.cfg delete mode 100644 .kokoro/samples/python3.8/periodic.cfg delete mode 100644 .kokoro/samples/python3.8/presubmit.cfg delete mode 100644 testing/constraints-3.7.txt delete mode 100644 testing/constraints-3.8.txt diff --git a/.github/workflows/presubmit.yaml b/.github/workflows/presubmit.yaml index 2d6132bd97..ab674fd370 100644 --- a/.github/workflows/presubmit.yaml +++ b/.github/workflows/presubmit.yaml @@ -17,7 +17,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v5 with: - python-version: 3.8 + python-version: 3.9 - name: Install nox run: python -m pip install nox - name: Check formatting @@ -27,7 +27,7 @@ jobs: strategy: fail-fast: false matrix: - python: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] + python: ["3.9", "3.10", "3.11", "3.12", "3.13"] steps: - name: Checkout code diff --git a/.kokoro/samples/python3.7/common.cfg b/.kokoro/samples/python3.7/common.cfg deleted file mode 100644 index 29ad87b5fc..0000000000 --- a/.kokoro/samples/python3.7/common.cfg +++ /dev/null @@ -1,40 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -# Build logs will be here -action { - define_artifacts { - regex: "**/*sponge_log.xml" - } -} - -# Specify which tests to run -env_vars: { - key: "RUN_TESTS_SESSION" - value: "py-3.7" -} - -# Declare build specific Cloud project. -env_vars: { - key: "BUILD_SPECIFIC_GCLOUD_PROJECT" - value: "python-docs-samples-tests-py37" -} - -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/python-spanner/.kokoro/test-samples.sh" -} - -# Configure the docker image for kokoro-trampoline. -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/python-samples-testing-docker" -} - -# Download secrets for samples -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/python-docs-samples" - -# Download trampoline resources. -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" - -# Use the trampoline script to run in docker. -build_file: "python-spanner/.kokoro/trampoline_v2.sh" \ No newline at end of file diff --git a/.kokoro/samples/python3.7/continuous.cfg b/.kokoro/samples/python3.7/continuous.cfg deleted file mode 100644 index a1c8d9759c..0000000000 --- a/.kokoro/samples/python3.7/continuous.cfg +++ /dev/null @@ -1,6 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -env_vars: { - key: "INSTALL_LIBRARY_FROM_SOURCE" - value: "True" -} \ No newline at end of file diff --git a/.kokoro/samples/python3.7/periodic-head.cfg b/.kokoro/samples/python3.7/periodic-head.cfg deleted file mode 100644 index b6133a1180..0000000000 --- a/.kokoro/samples/python3.7/periodic-head.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -env_vars: { - key: "INSTALL_LIBRARY_FROM_SOURCE" - value: "True" -} - -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/python-spanner/.kokoro/test-samples-against-head.sh" -} diff --git a/.kokoro/samples/python3.7/periodic.cfg b/.kokoro/samples/python3.7/periodic.cfg deleted file mode 100644 index 71cd1e597e..0000000000 --- a/.kokoro/samples/python3.7/periodic.cfg +++ /dev/null @@ -1,6 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -env_vars: { - key: "INSTALL_LIBRARY_FROM_SOURCE" - value: "False" -} diff --git a/.kokoro/samples/python3.7/presubmit.cfg b/.kokoro/samples/python3.7/presubmit.cfg deleted file mode 100644 index a1c8d9759c..0000000000 --- a/.kokoro/samples/python3.7/presubmit.cfg +++ /dev/null @@ -1,6 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -env_vars: { - key: "INSTALL_LIBRARY_FROM_SOURCE" - value: "True" -} \ No newline at end of file diff --git a/.kokoro/samples/python3.8/common.cfg b/.kokoro/samples/python3.8/common.cfg deleted file mode 100644 index 3f8d356809..0000000000 --- a/.kokoro/samples/python3.8/common.cfg +++ /dev/null @@ -1,40 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -# Build logs will be here -action { - define_artifacts { - regex: "**/*sponge_log.xml" - } -} - -# Specify which tests to run -env_vars: { - key: "RUN_TESTS_SESSION" - value: "py-3.8" -} - -# Declare build specific Cloud project. -env_vars: { - key: "BUILD_SPECIFIC_GCLOUD_PROJECT" - value: "python-docs-samples-tests-py38" -} - -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/python-spanner/.kokoro/test-samples.sh" -} - -# Configure the docker image for kokoro-trampoline. -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/python-samples-testing-docker" -} - -# Download secrets for samples -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/python-docs-samples" - -# Download trampoline resources. -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" - -# Use the trampoline script to run in docker. -build_file: "python-spanner/.kokoro/trampoline_v2.sh" \ No newline at end of file diff --git a/.kokoro/samples/python3.8/continuous.cfg b/.kokoro/samples/python3.8/continuous.cfg deleted file mode 100644 index a1c8d9759c..0000000000 --- a/.kokoro/samples/python3.8/continuous.cfg +++ /dev/null @@ -1,6 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -env_vars: { - key: "INSTALL_LIBRARY_FROM_SOURCE" - value: "True" -} \ No newline at end of file diff --git a/.kokoro/samples/python3.8/periodic-head.cfg b/.kokoro/samples/python3.8/periodic-head.cfg deleted file mode 100644 index b6133a1180..0000000000 --- a/.kokoro/samples/python3.8/periodic-head.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -env_vars: { - key: "INSTALL_LIBRARY_FROM_SOURCE" - value: "True" -} - -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/python-spanner/.kokoro/test-samples-against-head.sh" -} diff --git a/.kokoro/samples/python3.8/periodic.cfg b/.kokoro/samples/python3.8/periodic.cfg deleted file mode 100644 index 71cd1e597e..0000000000 --- a/.kokoro/samples/python3.8/periodic.cfg +++ /dev/null @@ -1,6 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -env_vars: { - key: "INSTALL_LIBRARY_FROM_SOURCE" - value: "False" -} diff --git a/.kokoro/samples/python3.8/presubmit.cfg b/.kokoro/samples/python3.8/presubmit.cfg deleted file mode 100644 index a1c8d9759c..0000000000 --- a/.kokoro/samples/python3.8/presubmit.cfg +++ /dev/null @@ -1,6 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -env_vars: { - key: "INSTALL_LIBRARY_FROM_SOURCE" - value: "True" -} \ No newline at end of file diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 608f4654f6..76e9061cd2 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -22,7 +22,7 @@ In order to add a feature: documentation. - The feature must work fully on the following CPython versions: - 3.7, 3.8, 3.9, 3.10, 3.11, 3.12 and 3.13 on both UNIX and Windows. + 3.9, 3.10, 3.11, 3.12 and 3.13 on both UNIX and Windows. - The feature must not add unnecessary dependencies (where "unnecessary" is of course subjective, but new dependencies should @@ -143,12 +143,12 @@ Running System Tests $ nox -s system # Run a single system test - $ nox -s system-3.8 -- -k + $ nox -s system-3.12 -- -k .. note:: - System tests are only configured to run under Python 3.8. + System tests are only configured to run under Python 3.12. For expediency, we do not run them in older versions of Python 3. This alone will not run the tests. You'll need to change some local @@ -195,11 +195,11 @@ configure them just like the System Tests. # Run all tests in a folder $ cd samples/samples - $ nox -s py-3.8 + $ nox -s py-3.9 # Run a single sample test $ cd samples/samples - $ nox -s py-3.8 -- -k + $ nox -s py-3.9 -- -k ******************************************** Note About ``README`` as it pertains to PyPI @@ -221,16 +221,12 @@ Supported Python Versions We support: -- `Python 3.7`_ -- `Python 3.8`_ - `Python 3.9`_ - `Python 3.10`_ - `Python 3.11`_ - `Python 3.12`_ - `Python 3.13`_ -.. _Python 3.7: https://docs.python.org/3.7/ -.. _Python 3.8: https://docs.python.org/3.8/ .. _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/ @@ -243,7 +239,7 @@ Supported versions can be found in our ``noxfile.py`` `config`_. .. _config: https://github.com/googleapis/python-spanner/blob/main/noxfile.py -We also explicitly decided to support Python 3 beginning with version 3.7. +We also explicitly decided to support Python 3 beginning with version 3.9. Reasons for this include: - Encouraging use of newest versions of Python 3 diff --git a/README.rst b/README.rst index 085587e51d..2b1f7b0acd 100644 --- a/README.rst +++ b/README.rst @@ -56,14 +56,15 @@ dependencies. Supported Python Versions ^^^^^^^^^^^^^^^^^^^^^^^^^ -Python >= 3.7 +Python >= 3.9 Deprecated Python Versions ^^^^^^^^^^^^^^^^^^^^^^^^^^ Python == 2.7. Python == 3.5. Python == 3.6. - +Python == 3.7. +Python == 3.8. Mac/Linux ^^^^^^^^^ diff --git a/noxfile.py b/noxfile.py index 107437249e..00ba1d429a 100644 --- a/noxfile.py +++ b/noxfile.py @@ -38,8 +38,6 @@ SYSTEM_TEST_PYTHON_VERSIONS: List[str] = ["3.12"] UNIT_TEST_PYTHON_VERSIONS: List[str] = [ - "3.7", - "3.8", "3.9", "3.10", "3.11", @@ -78,8 +76,6 @@ CURRENT_DIRECTORY = pathlib.Path(__file__).parent.absolute() nox.options.sessions = [ - # TODO(https://github.com/googleapis/python-spanner/issues/1392): - # Remove or restore testing for Python 3.7/3.8 "unit-3.9", "unit-3.10", "unit-3.11", diff --git a/owlbot.py b/owlbot.py index ce4b00af28..cf460877a3 100644 --- a/owlbot.py +++ b/owlbot.py @@ -236,6 +236,8 @@ def get_staging_dirs( ".github/release-please.yml", ".kokoro/test-samples-impl.sh", ".kokoro/presubmit/presubmit.cfg", + ".kokoro/samples/python3.7/**", + ".kokoro/samples/python3.8/**", ], ) @@ -259,6 +261,17 @@ def get_staging_dirs( python.py_samples() +s.replace( + "samples/**/noxfile.py", + 'BLACK_VERSION = "black==22.3.0"', + 'BLACK_VERSION = "black==23.7.0"', +) +s.replace( + "samples/**/noxfile.py", + r'ALL_VERSIONS = \["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"\]', + 'ALL_VERSIONS = ["3.9", "3.10", "3.11", "3.12", "3.13"]', +) + # Use a python runtime which is available in the owlbot post processor here # https://github.com/googleapis/synthtool/blob/master/docker/owlbot/python/Dockerfile s.shell.run(["nox", "-s", "blacken-3.10"], hide_output=False) diff --git a/samples/samples/noxfile.py b/samples/samples/noxfile.py index a169b5b5b4..6da83b5c9f 100644 --- a/samples/samples/noxfile.py +++ b/samples/samples/noxfile.py @@ -89,7 +89,7 @@ def get_pytest_env_vars() -> Dict[str, str]: # DO NOT EDIT - automatically generated. # All versions used to test samples. -ALL_VERSIONS = ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] +ALL_VERSIONS = ["3.9", "3.10", "3.11", "3.12", "3.13"] # Any default versions that should be ignored. IGNORED_VERSIONS = TEST_CONFIG["ignored_versions"] diff --git a/setup.py b/setup.py index a32883075b..858982f783 100644 --- a/setup.py +++ b/setup.py @@ -86,8 +86,6 @@ "License :: OSI Approved :: Apache Software License", "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", @@ -99,7 +97,7 @@ packages=packages, install_requires=dependencies, extras_require=extras, - python_requires=">=3.7", + python_requires=">=3.9", include_package_data=True, zip_safe=False, ) diff --git a/testing/constraints-3.7.txt b/testing/constraints-3.7.txt deleted file mode 100644 index 58482dcd03..0000000000 --- a/testing/constraints-3.7.txt +++ /dev/null @@ -1,20 +0,0 @@ -# This constraints file is used to check that lower bounds -# are correct in setup.py -# List all library dependencies and extras in this file. -# Pin the version to the lower bound. -# e.g., if setup.py has "google-cloud-foo >= 1.14.0, < 2.0.0dev", -# Then this file should have google-cloud-foo==1.14.0 -google-api-core==1.34.0 -google-cloud-core==1.4.4 -grpc-google-iam-v1==0.12.4 -libcst==0.2.5 -proto-plus==1.22.0 -sqlparse==0.4.4 -opentelemetry-api==1.22.0 -opentelemetry-sdk==1.22.0 -opentelemetry-semantic-conventions==0.43b0 -protobuf==3.20.2 -deprecated==1.2.14 -grpc-interceptor==0.15.4 -google-cloud-monitoring==2.16.0 -mmh3==4.1.0 diff --git a/testing/constraints-3.8.txt b/testing/constraints-3.8.txt deleted file mode 100644 index ad3f0fa58e..0000000000 --- a/testing/constraints-3.8.txt +++ /dev/null @@ -1,7 +0,0 @@ -# -*- coding: utf-8 -*- -# This constraints file is required for unit tests. -# List all library dependencies and extras in this file. -google-api-core -proto-plus -protobuf -grpc-google-iam-v1 From f744a1622660c15b47d9f440740ecc1788912740 Mon Sep 17 00:00:00 2001 From: Owl Bot Date: Wed, 6 Aug 2025 06:09:12 +0000 Subject: [PATCH 2/6] =?UTF-8?q?=F0=9F=A6=89=20Updates=20from=20OwlBot=20po?= =?UTF-8?q?st-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 --- samples/samples/noxfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/samples/noxfile.py b/samples/samples/noxfile.py index 6da83b5c9f..97dc6241e7 100644 --- a/samples/samples/noxfile.py +++ b/samples/samples/noxfile.py @@ -29,7 +29,7 @@ # WARNING - WARNING - WARNING - WARNING - WARNING # WARNING - WARNING - WARNING - WARNING - WARNING -BLACK_VERSION = "black==22.3.0" +BLACK_VERSION = "black==23.7.0" ISORT_VERSION = "isort==5.10.1" # Copy `noxfile_config.py` to your directory and modify it instead. From 606987dfb5ba95d689868be1f7f4155624a19081 Mon Sep 17 00:00:00 2001 From: rahul yadav Date: Wed, 6 Aug 2025 12:35:01 +0530 Subject: [PATCH 3/6] fix build --- noxfile.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/noxfile.py b/noxfile.py index 00ba1d429a..b101f46b2e 100644 --- a/noxfile.py +++ b/noxfile.py @@ -512,11 +512,12 @@ def prerelease_deps(session, protobuf_implementation, database_dialect): constraints_deps = [ match.group(1) for match in re.finditer( - r"^\s*(\S+)(?===\S+)", constraints_text, flags=re.MULTILINE + r"^\s*([a-zA-Z0-9._-]+)", constraints_text, flags=re.MULTILINE ) ] - session.install(*constraints_deps) + if constraints_deps: + session.install(*constraints_deps) prerel_deps = [ "protobuf", From 53c4de215a5c653efab7743e25e10fd706d048d5 Mon Sep 17 00:00:00 2001 From: rahul yadav Date: Wed, 6 Aug 2025 12:52:07 +0530 Subject: [PATCH 4/6] update required check --- .github/sync-repo-settings.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/sync-repo-settings.yaml b/.github/sync-repo-settings.yaml index 5b2a506d17..d726d1193d 100644 --- a/.github/sync-repo-settings.yaml +++ b/.github/sync-repo-settings.yaml @@ -11,5 +11,5 @@ branchProtectionRules: - 'Kokoro system-3.12' - 'cla/google' - 'Samples - Lint' - - 'Samples - Python 3.8' + - 'Samples - Python 3.9' - 'Samples - Python 3.12' From 7299164c014a2f2374bbdcf4b83540fecce4b67b Mon Sep 17 00:00:00 2001 From: rahul yadav Date: Mon, 25 Aug 2025 11:04:54 +0530 Subject: [PATCH 5/6] fix test --- samples/samples/snippets_test.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/samples/samples/snippets_test.py b/samples/samples/snippets_test.py index 01482518db..46fc658596 100644 --- a/samples/samples/snippets_test.py +++ b/samples/samples/snippets_test.py @@ -680,13 +680,20 @@ def test_write_with_dml_transaction(capsys, instance_id, sample_database): @pytest.mark.dependency(depends=["add_column"]) -def update_data_with_partitioned_dml(capsys, instance_id, sample_database): +def test_update_data_with_partitioned_dml(capsys, instance_id, sample_database): snippets.update_data_with_partitioned_dml(instance_id, sample_database.database_id) out, _ = capsys.readouterr() assert "3 record(s) updated" in out -@pytest.mark.dependency(depends=["insert_with_dml"]) +@pytest.mark.dependency( + depends=[ + "insert_with_dml", + "dml_write_read_transaction", + "log_commit_stats", + "set_max_commit_delay", + ] +) def test_delete_data_with_partitioned_dml(capsys, instance_id, sample_database): snippets.delete_data_with_partitioned_dml(instance_id, sample_database.database_id) out, _ = capsys.readouterr() From 3d6c19cd9b5c58a368f9614894811800a7c6ef4d Mon Sep 17 00:00:00 2001 From: rahul yadav Date: Tue, 26 Aug 2025 10:27:43 +0530 Subject: [PATCH 6/6] fix tests --- samples/samples/snippets.py | 4 ++-- samples/samples/snippets_test.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/samples/snippets.py b/samples/samples/snippets.py index 92fdd99132..87b7ab86a2 100644 --- a/samples/samples/snippets.py +++ b/samples/samples/snippets.py @@ -1591,9 +1591,9 @@ def __init__(self): super().__init__("commit_stats_sample") def info(self, msg, *args, **kwargs): - if kwargs["extra"] and "commit_stats" in kwargs["extra"]: + if "extra" in kwargs and kwargs["extra"] and "commit_stats" in kwargs["extra"]: self.last_commit_stats = kwargs["extra"]["commit_stats"] - super().info(msg) + super().info(msg, *args, **kwargs) spanner_client = spanner.Client() instance = spanner_client.instance(instance_id) diff --git a/samples/samples/snippets_test.py b/samples/samples/snippets_test.py index 46fc658596..72f243fdb5 100644 --- a/samples/samples/snippets_test.py +++ b/samples/samples/snippets_test.py @@ -683,7 +683,7 @@ def test_write_with_dml_transaction(capsys, instance_id, sample_database): def test_update_data_with_partitioned_dml(capsys, instance_id, sample_database): snippets.update_data_with_partitioned_dml(instance_id, sample_database.database_id) out, _ = capsys.readouterr() - assert "3 record(s) updated" in out + assert "3 records updated" in out @pytest.mark.dependency(