From a226a7a8a668d5f34dcb0aa4f9dc1ddab579b63d Mon Sep 17 00:00:00 2001 From: Dev-iL <6509619+Dev-iL@users.noreply.github.com> Date: Sun, 22 Mar 2026 14:56:44 +0200 Subject: [PATCH] Add Python 3.14 Support Un-exclude the google provider from py3.14 --- dev/breeze/tests/test_selective_checks.py | 1 - providers/google/docs/changelog.rst | 8 +++++++- providers/google/provider.yaml | 3 --- providers/google/pyproject.toml | 3 ++- .../src/airflow/providers/google/cloud/hooks/ray.py | 5 +++++ .../tests/unit/google/cloud/hooks/test_bigquery_dts.py | 8 ++++---- .../google/tests/unit/google/cloud/hooks/test_ray.py | 6 +++++- .../tests/unit/google/cloud/hooks/vertex_ai/test_ray.py | 2 +- .../google/tests/unit/google/cloud/links/test_ray.py | 4 ++++ .../google/tests/unit/google/cloud/operators/test_ray.py | 3 +++ .../tests/unit/google/cloud/triggers/test_dataproc.py | 5 +---- pyproject.toml | 4 ++-- .../tests/ci/prek/test_check_excluded_provider_markers.py | 1 - uv.lock | 8 ++++---- 14 files changed, 38 insertions(+), 23 deletions(-) diff --git a/dev/breeze/tests/test_selective_checks.py b/dev/breeze/tests/test_selective_checks.py index a870616b06fac..86cfec230847d 100644 --- a/dev/breeze/tests/test_selective_checks.py +++ b/dev/breeze/tests/test_selective_checks.py @@ -1385,7 +1385,6 @@ def test_excluded_providers(): "3.14": [ "amazon", # Depends on lxml<6 "apache.cassandra", # Enable when the next release after 3.29.3 is available - "google", # Depends on ray, which does not yet support python 3.14 (due to pydantic v1) ], } ), diff --git a/providers/google/docs/changelog.rst b/providers/google/docs/changelog.rst index 041d1f8127818..485a46574f0bd 100644 --- a/providers/google/docs/changelog.rst +++ b/providers/google/docs/changelog.rst @@ -31,6 +31,11 @@ Changelog 21.0.0 ...... +.. note:: + This version of the provider introduces support for Python 3.14. + However, the Ray package doesn't yet support Python 3.14, thus ``RayJobHook`` will not work. + If you use ``RayJobHook`` you should stay on Python<3.14 until the upstream library issues a fix. + .. warning:: Deprecated classes, parameters and features have been removed from the Google provider package. The following breaking changes were introduced: @@ -193,7 +198,8 @@ Doc-only ...... .. warning:: - We have identified the following regressions for this version. + We have identified the following regressions for this version: + - The return value of the ``GenAIGeminiCreateBatchJobOperator`` and ``GenAIGeminiGetBatchJobOperator`` were incompatible with Airflow 2. The issues fixed in the following PRs #61253 and #61842. - The ``transport`` parameter broke the deferrable mode for ``CloudRunExecuteJobOperator``. The issue fixed in #61546. diff --git a/providers/google/provider.yaml b/providers/google/provider.yaml index f123cbd7b47a8..04541d5569d92 100644 --- a/providers/google/provider.yaml +++ b/providers/google/provider.yaml @@ -123,9 +123,6 @@ versions: - 2.0.0 - 1.0.0 -excluded-python-versions: - - "3.14" - integrations: - integration-name: Google Analytics (GA4) external-doc-url: https://analytics.google.com/ diff --git a/providers/google/pyproject.toml b/providers/google/pyproject.toml index 562bf9af04a3b..25013e9f7f5a7 100644 --- a/providers/google/pyproject.toml +++ b/providers/google/pyproject.toml @@ -49,9 +49,10 @@ classifiers = [ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Topic :: System :: Monitoring", ] -requires-python = ">=3.10,!=3.14.*" +requires-python = ">=3.10" # The dependencies should be modified in place in the generated file. # Any change in the dependencies is preserved when the file is regenerated diff --git a/providers/google/src/airflow/providers/google/cloud/hooks/ray.py b/providers/google/src/airflow/providers/google/cloud/hooks/ray.py index bda6ab086aee1..75267ef485b84 100644 --- a/providers/google/src/airflow/providers/google/cloud/hooks/ray.py +++ b/providers/google/src/airflow/providers/google/cloud/hooks/ray.py @@ -19,9 +19,14 @@ from __future__ import annotations +import sys from typing import TYPE_CHECKING, Any from urllib.parse import urlparse +# Remove the below after https://github.com/ray-project/ray/issues/56434 is resolved +if sys.version_info >= (3, 14): + raise ImportError("Ray is not supported on Python 3.14 yet") + from ray.job_submission import JobSubmissionClient from airflow.providers.google.common.hooks.base_google import GoogleBaseHook diff --git a/providers/google/tests/unit/google/cloud/hooks/test_bigquery_dts.py b/providers/google/tests/unit/google/cloud/hooks/test_bigquery_dts.py index 3ee7328e03f87..f94ba9b4b15b1 100644 --- a/providers/google/tests/unit/google/cloud/hooks/test_bigquery_dts.py +++ b/providers/google/tests/unit/google/cloud/hooks/test_bigquery_dts.py @@ -134,10 +134,6 @@ def mock_client(self): f"{self.HOOK_MODULE_PATH}.AsyncBiqQueryDataTransferServiceHook._get_conn", new_callable=AsyncMock, ) as mock_client: - transfer_result = Future() - transfer_result.set_result(mock.MagicMock()) - - mock_client.return_value.get_transfer_run = mock.MagicMock(return_value=transfer_result) yield mock_client @pytest.fixture @@ -147,6 +143,10 @@ def hook(self): @pytest.mark.db_test @pytest.mark.asyncio async def test_get_transfer_run(self, mock_client, hook): + transfer_result = Future() + transfer_result.set_result(mock.MagicMock()) + mock_client.return_value.get_transfer_run = mock.MagicMock(return_value=transfer_result) + await hook.get_transfer_run( run_id=RUN_ID, config_id=TRANSFER_CONFIG_ID, diff --git a/providers/google/tests/unit/google/cloud/hooks/test_ray.py b/providers/google/tests/unit/google/cloud/hooks/test_ray.py index e22c07204ac1f..02b45ca0cb212 100644 --- a/providers/google/tests/unit/google/cloud/hooks/test_ray.py +++ b/providers/google/tests/unit/google/cloud/hooks/test_ray.py @@ -19,12 +19,16 @@ from unittest import mock -from airflow.providers.google.cloud.hooks.ray import RayJobHook +import pytest from unit.google.cloud.utils.base_gcp_mock import ( mock_base_gcp_hook_default_project_id, ) +# Remove the below workaround once https://github.com/ray-project/ray/issues/56434 is resolved +pytest.importorskip("airflow.providers.google.cloud.hooks.ray") +from airflow.providers.google.cloud.hooks.ray import RayJobHook + TEST_GCP_CONN_ID: str = "test-gcp-conn-id" TEST_CLUSTER_NAME: str = "test-cluster-name" diff --git a/providers/google/tests/unit/google/cloud/hooks/vertex_ai/test_ray.py b/providers/google/tests/unit/google/cloud/hooks/vertex_ai/test_ray.py index c4905cc1c52c8..d3d071c4b3ffd 100644 --- a/providers/google/tests/unit/google/cloud/hooks/vertex_ai/test_ray.py +++ b/providers/google/tests/unit/google/cloud/hooks/vertex_ai/test_ray.py @@ -21,7 +21,7 @@ import pytest -resources = pytest.importorskip("google.cloud.aiplatform.vertex_ray.util.resources") +pytest.importorskip("google.cloud.aiplatform.vertex_ray.util.resources") from google.cloud.aiplatform.vertex_ray.util.resources import Cluster, Resources from airflow.providers.google.cloud.hooks.vertex_ai.ray import RayHook diff --git a/providers/google/tests/unit/google/cloud/links/test_ray.py b/providers/google/tests/unit/google/cloud/links/test_ray.py index e7b51b9932231..34e6c9c0aaaf1 100644 --- a/providers/google/tests/unit/google/cloud/links/test_ray.py +++ b/providers/google/tests/unit/google/cloud/links/test_ray.py @@ -19,6 +19,10 @@ from unittest import mock +import pytest + +# Remove the below workaround once https://github.com/ray-project/ray/issues/56434 is resolved +pytest.importorskip("ray.dashboard.modules.job.common") from airflow.providers.google.cloud.links.ray import RayJobLink TEST_CLUSTER_ADDRESS = "ray-head-123.us-central1.ray.googleusercontent.com" diff --git a/providers/google/tests/unit/google/cloud/operators/test_ray.py b/providers/google/tests/unit/google/cloud/operators/test_ray.py index 3256925803a10..5d8aee1f17222 100644 --- a/providers/google/tests/unit/google/cloud/operators/test_ray.py +++ b/providers/google/tests/unit/google/cloud/operators/test_ray.py @@ -19,6 +19,9 @@ from unittest import mock import pytest + +# Remove the below workaround once https://github.com/ray-project/ray/issues/56434 is resolved +pytest.importorskip("ray.dashboard.modules.job.common") from ray.dashboard.modules.job.common import JobStatus from airflow.providers.common.compat.sdk import AirflowTaskTimeout diff --git a/providers/google/tests/unit/google/cloud/triggers/test_dataproc.py b/providers/google/tests/unit/google/cloud/triggers/test_dataproc.py index ed3e5c08f3610..1e0f917649789 100644 --- a/providers/google/tests/unit/google/cloud/triggers/test_dataproc.py +++ b/providers/google/tests/unit/google/cloud/triggers/test_dataproc.py @@ -210,10 +210,7 @@ async def test_async_cluster_triggers_on_success_should_execute_successfully( @pytest.mark.db_test @pytest.mark.asyncio @mock.patch("airflow.providers.google.cloud.triggers.dataproc.DataprocClusterTrigger.fetch_cluster") - @mock.patch( - "airflow.providers.google.cloud.hooks.dataproc.DataprocAsyncHook.delete_cluster", - return_value=asyncio.Future(), - ) + @mock.patch("airflow.providers.google.cloud.hooks.dataproc.DataprocAsyncHook.delete_cluster") @mock.patch("google.auth.default") async def test_async_cluster_trigger_run_returns_error_event( self, mock_auth, mock_delete_cluster, mock_fetch_cluster, cluster_trigger, async_get_cluster, caplog diff --git a/pyproject.toml b/pyproject.toml index 26287e61dd02d..812f4c13147d7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -230,7 +230,7 @@ packages = [] "apache-airflow-providers-github>=2.8.0" ] "google" = [ - "apache-airflow-providers-google>=10.24.0; python_version !=\"3.14\"" + "apache-airflow-providers-google>=10.24.0" ] "grpc" = [ "apache-airflow-providers-grpc>=3.7.0" @@ -436,7 +436,7 @@ packages = [] "apache-airflow-providers-ftp>=3.12.0", "apache-airflow-providers-git>=0.0.2", # Set from MIN_VERSION_OVERRIDE in update_airflow_pyproject_toml.py "apache-airflow-providers-github>=2.8.0", - "apache-airflow-providers-google>=10.24.0; python_version !=\"3.14\"", + "apache-airflow-providers-google>=10.24.0", "apache-airflow-providers-grpc>=3.7.0", "apache-airflow-providers-hashicorp>=4.0.0", "apache-airflow-providers-http>=4.13.2", diff --git a/scripts/tests/ci/prek/test_check_excluded_provider_markers.py b/scripts/tests/ci/prek/test_check_excluded_provider_markers.py index 62ca32728d33d..159e7bd2bde6b 100644 --- a/scripts/tests/ci/prek/test_check_excluded_provider_markers.py +++ b/scripts/tests/ci/prek/test_check_excluded_provider_markers.py @@ -21,7 +21,6 @@ EXCLUDED = { "apache-airflow-providers-amazon": ["3.14"], - "apache-airflow-providers-google": ["3.14"], } diff --git a/uv.lock b/uv.lock index 26c6d6d2f9a49..653885f7f2e55 100644 --- a/uv.lock +++ b/uv.lock @@ -883,7 +883,7 @@ all = [ { name = "apache-airflow-providers-ftp" }, { name = "apache-airflow-providers-git" }, { name = "apache-airflow-providers-github" }, - { name = "apache-airflow-providers-google", marker = "python_full_version != '3.14.*'" }, + { name = "apache-airflow-providers-google" }, { name = "apache-airflow-providers-grpc" }, { name = "apache-airflow-providers-hashicorp" }, { name = "apache-airflow-providers-http" }, @@ -1100,7 +1100,7 @@ github-enterprise = [ { name = "authlib" }, ] google = [ - { name = "apache-airflow-providers-google", marker = "python_full_version != '3.14.*'" }, + { name = "apache-airflow-providers-google" }, ] google-auth = [ { name = "apache-airflow-providers-fab" }, @@ -1451,8 +1451,8 @@ requires-dist = [ { name = "apache-airflow-providers-git", marker = "extra == 'git'", editable = "providers/git" }, { name = "apache-airflow-providers-github", marker = "extra == 'all'", editable = "providers/github" }, { name = "apache-airflow-providers-github", marker = "extra == 'github'", editable = "providers/github" }, - { name = "apache-airflow-providers-google", marker = "python_full_version != '3.14.*' and extra == 'all'", editable = "providers/google" }, - { name = "apache-airflow-providers-google", marker = "python_full_version != '3.14.*' and extra == 'google'", editable = "providers/google" }, + { name = "apache-airflow-providers-google", marker = "extra == 'all'", editable = "providers/google" }, + { name = "apache-airflow-providers-google", marker = "extra == 'google'", editable = "providers/google" }, { name = "apache-airflow-providers-grpc", marker = "extra == 'all'", editable = "providers/grpc" }, { name = "apache-airflow-providers-grpc", marker = "extra == 'grpc'", editable = "providers/grpc" }, { name = "apache-airflow-providers-hashicorp", marker = "extra == 'all'", editable = "providers/hashicorp" },