This is an automated email from the ASF dual-hosted git repository.

ephraimanierobi pushed a commit to branch v2-8-test
in repository https://gitbox.apache.org/repos/asf/airflow.git

commit b331cb2e0e3c47e3e2322decba29cba1d6f1aecf
Author: Sin-Woo Bang <sinwoob...@gmail.com>
AuthorDate: Wed Nov 22 20:56:43 2023 +0900

    Upgrade to Pydantic v2 (#35551)
    
    * Replace deprecated Config with ConfigDict
    
    * Drop Pydantic v1 compatibility as bumping it to 2.3.0
---
 airflow/configuration.py                       |  4 ----
 airflow/serialization/pydantic/dag.py          | 29 +++++++++-----------------
 airflow/serialization/pydantic/dag_run.py      |  9 ++------
 airflow/serialization/pydantic/dataset.py      | 27 +++++-------------------
 airflow/serialization/pydantic/job.py          |  8 ++-----
 airflow/serialization/pydantic/taskinstance.py |  9 ++------
 airflow/serialization/serde.py                 |  9 +-------
 airflow/serialization/serialized_objects.py    |  5 +----
 setup.cfg                                      |  6 +-----
 9 files changed, 24 insertions(+), 82 deletions(-)

diff --git a/airflow/configuration.py b/airflow/configuration.py
index 6b03759033..1df62c9b99 100644
--- a/airflow/configuration.py
+++ b/airflow/configuration.py
@@ -62,10 +62,6 @@ if not sys.warnoptions:
     warnings.filterwarnings(action="default", category=DeprecationWarning, 
module="airflow")
     warnings.filterwarnings(action="default", 
category=PendingDeprecationWarning, module="airflow")
 
-    # Temporarily suppress warnings from pydantic until we upgrade minimum 
version of pydantic to v2
-    # Which should happen in Airflow 2.8.0
-    warnings.filterwarnings(action="ignore", category=UserWarning, 
module=r"pydantic._internal._config")
-
 _SQLITE3_VERSION_PATTERN = re2.compile(r"(?P<version>^\d+(?:\.\d+)*)\D?.*$")
 
 ConfigType = Union[str, int, float, bool]
diff --git a/airflow/serialization/pydantic/dag.py 
b/airflow/serialization/pydantic/dag.py
index 6631afdf73..04b2472355 100644
--- a/airflow/serialization/pydantic/dag.py
+++ b/airflow/serialization/pydantic/dag.py
@@ -21,7 +21,13 @@ from datetime import datetime, timedelta
 from typing import Any, List, Optional
 
 from dateutil import relativedelta
-from pydantic import BaseModel as BaseModelPydantic, PlainSerializer, 
PlainValidator, ValidationInfo
+from pydantic import (
+    BaseModel as BaseModelPydantic,
+    ConfigDict,
+    PlainSerializer,
+    PlainValidator,
+    ValidationInfo,
+)
 from typing_extensions import Annotated
 
 from airflow import DAG, settings
@@ -86,12 +92,7 @@ class DagOwnerAttributesPydantic(BaseModelPydantic):
     owner: str
     link: str
 
-    class Config:
-        """Make sure it deals automatically with SQLAlchemy ORM classes."""
-
-        from_attributes = True
-        orm_mode = True  # Pydantic 1.x compatibility.
-        arbitrary_types_allowed = True
+    model_config = ConfigDict(from_attributes=True, 
arbitrary_types_allowed=True)
 
 
 class DagTagPydantic(BaseModelPydantic):
@@ -100,12 +101,7 @@ class DagTagPydantic(BaseModelPydantic):
     name: str
     dag_id: str
 
-    class Config:
-        """Make sure it deals automatically with SQLAlchemy ORM classes."""
-
-        from_attributes = True
-        orm_mode = True  # Pydantic 1.x compatibility.
-        arbitrary_types_allowed = True
+    model_config = ConfigDict(from_attributes=True, 
arbitrary_types_allowed=True)
 
 
 class DagModelPydantic(BaseModelPydantic):
@@ -141,12 +137,7 @@ class DagModelPydantic(BaseModelPydantic):
 
     _processor_dags_folder: Optional[str] = None
 
-    class Config:
-        """Make sure it deals automatically with SQLAlchemy ORM classes."""
-
-        from_attributes = True
-        orm_mode = True  # Pydantic 1.x compatibility.
-        arbitrary_types_allowed = True
+    model_config = ConfigDict(from_attributes=True, 
arbitrary_types_allowed=True)
 
     @property
     def relative_fileloc(self) -> pathlib.Path:
diff --git a/airflow/serialization/pydantic/dag_run.py 
b/airflow/serialization/pydantic/dag_run.py
index aaa4372a50..cd0886ecaf 100644
--- a/airflow/serialization/pydantic/dag_run.py
+++ b/airflow/serialization/pydantic/dag_run.py
@@ -19,7 +19,7 @@ from __future__ import annotations
 from datetime import datetime
 from typing import TYPE_CHECKING, Iterable, List, Optional
 
-from pydantic import BaseModel as BaseModelPydantic
+from pydantic import BaseModel as BaseModelPydantic, ConfigDict
 
 from airflow.serialization.pydantic.dag import PydanticDag
 from airflow.serialization.pydantic.dataset import DatasetEventPydantic
@@ -56,12 +56,7 @@ class DagRunPydantic(BaseModelPydantic):
     dag: Optional[PydanticDag]
     consumed_dataset_events: List[DatasetEventPydantic]  # noqa
 
-    class Config:
-        """Make sure it deals automatically with SQLAlchemy ORM classes."""
-
-        from_attributes = True
-        orm_mode = True  # Pydantic 1.x compatibility.
-        arbitrary_types_allowed = True
+    model_config = ConfigDict(from_attributes=True, 
arbitrary_types_allowed=True)
 
     @property
     def logical_date(self) -> datetime:
diff --git a/airflow/serialization/pydantic/dataset.py 
b/airflow/serialization/pydantic/dataset.py
index 14255c8271..0c233a3fd6 100644
--- a/airflow/serialization/pydantic/dataset.py
+++ b/airflow/serialization/pydantic/dataset.py
@@ -17,7 +17,7 @@
 from datetime import datetime
 from typing import List, Optional
 
-from pydantic import BaseModel as BaseModelPydantic
+from pydantic import BaseModel as BaseModelPydantic, ConfigDict
 
 
 class DagScheduleDatasetReferencePydantic(BaseModelPydantic):
@@ -28,11 +28,7 @@ class DagScheduleDatasetReferencePydantic(BaseModelPydantic):
     created_at: datetime
     updated_at: datetime
 
-    class Config:
-        """Make sure it deals automatically with SQLAlchemy ORM classes."""
-
-        from_attributes = True
-        orm_mode = True  # Pydantic 1.x compatibility.
+    model_config = ConfigDict(from_attributes=True)
 
 
 class TaskOutletDatasetReferencePydantic(BaseModelPydantic):
@@ -44,11 +40,7 @@ class TaskOutletDatasetReferencePydantic(BaseModelPydantic):
     created_at: datetime
     updated_at: datetime
 
-    class Config:
-        """Make sure it deals automatically with SQLAlchemy ORM classes."""
-
-        from_attributes = True
-        orm_mode = True  # Pydantic 1.x compatibility.
+    model_config = ConfigDict(from_attributes=True)
 
 
 class DatasetPydantic(BaseModelPydantic):
@@ -64,11 +56,7 @@ class DatasetPydantic(BaseModelPydantic):
     consuming_dags: List[DagScheduleDatasetReferencePydantic]
     producing_tasks: List[TaskOutletDatasetReferencePydantic]
 
-    class Config:
-        """Make sure it deals automatically with SQLAlchemy ORM classes."""
-
-        from_attributes = True
-        orm_mode = True  # Pydantic 1.x compatibility.
+    model_config = ConfigDict(from_attributes=True)
 
 
 class DatasetEventPydantic(BaseModelPydantic):
@@ -84,9 +72,4 @@ class DatasetEventPydantic(BaseModelPydantic):
     timestamp: datetime
     dataset: Optional[DatasetPydantic]
 
-    class Config:
-        """Make sure it deals automatically with SQLAlchemy ORM classes."""
-
-        from_attributes = True
-        orm_mode = True  # Pydantic 1.x compatibility.
-        arbitrary_types_allowed = True
+    model_config = ConfigDict(from_attributes=True, 
arbitrary_types_allowed=True)
diff --git a/airflow/serialization/pydantic/job.py 
b/airflow/serialization/pydantic/job.py
index eb92411090..2db30ab2c8 100644
--- a/airflow/serialization/pydantic/job.py
+++ b/airflow/serialization/pydantic/job.py
@@ -18,7 +18,7 @@ import datetime
 from functools import cached_property
 from typing import Optional
 
-from pydantic import BaseModel as BaseModelPydantic
+from pydantic import BaseModel as BaseModelPydantic, ConfigDict
 
 from airflow.executors.executor_loader import ExecutorLoader
 from airflow.jobs.base_job_runner import BaseJobRunner
@@ -44,11 +44,7 @@ class JobPydantic(BaseModelPydantic):
     hostname: Optional[str]
     unixname: Optional[str]
 
-    class Config:
-        """Make sure it deals automatically with SQLAlchemy ORM classes."""
-
-        from_attributes = True
-        orm_mode = True  # Pydantic 1.x compatibility.
+    model_config = ConfigDict(from_attributes=True)
 
     @cached_property
     def executor(self):
diff --git a/airflow/serialization/pydantic/taskinstance.py 
b/airflow/serialization/pydantic/taskinstance.py
index 0043bfaef0..106a31186e 100644
--- a/airflow/serialization/pydantic/taskinstance.py
+++ b/airflow/serialization/pydantic/taskinstance.py
@@ -19,7 +19,7 @@ from __future__ import annotations
 from datetime import datetime
 from typing import TYPE_CHECKING, Any, Iterable, Optional
 
-from pydantic import BaseModel as BaseModelPydantic, PlainSerializer, 
PlainValidator
+from pydantic import BaseModel as BaseModelPydantic, ConfigDict, 
PlainSerializer, PlainValidator
 from typing_extensions import Annotated
 
 from airflow.models import Operator
@@ -105,12 +105,7 @@ class TaskInstancePydantic(BaseModelPydantic, 
LoggingMixin):
     dag_run: Optional[DagRunPydantic]
     dag_model: Optional[DagModelPydantic]
 
-    class Config:
-        """Make sure it deals automatically with SQLAlchemy ORM classes."""
-
-        from_attributes = True
-        orm_mode = True  # Pydantic 1.x compatibility.
-        arbitrary_types_allowed = True
+    model_config = ConfigDict(from_attributes=True, 
arbitrary_types_allowed=True)
 
     def init_run_context(self, raw: bool = False) -> None:
         """Set the log context."""
diff --git a/airflow/serialization/serde.py b/airflow/serialization/serde.py
index c86f643505..23d67e6162 100644
--- a/airflow/serialization/serde.py
+++ b/airflow/serialization/serde.py
@@ -319,14 +319,7 @@ def _is_pydantic(cls: Any) -> bool:
     Checking is done by attributes as it is significantly faster than
     using isinstance.
     """
-    return (
-        hasattr(cls, "__validators__")
-        and hasattr(cls, "__fields__")
-        and hasattr(cls, "dict")  # Pydantic v1
-        or hasattr(cls, "model_config")
-        and hasattr(cls, "model_fields")
-        and hasattr(cls, "model_fields_set")  # Pydantic v2
-    )
+    return hasattr(cls, "model_config") and hasattr(cls, "model_fields") and 
hasattr(cls, "model_fields_set")
 
 
 def _register():
diff --git a/airflow/serialization/serialized_objects.py 
b/airflow/serialization/serialized_objects.py
index 889177f4c1..9d7955bf01 100644
--- a/airflow/serialization/serialized_objects.py
+++ b/airflow/serialization/serialized_objects.py
@@ -502,10 +502,7 @@ class BaseSerialization:
         elif use_pydantic_models and _ENABLE_AIP_44:
 
             def _pydantic_model_dump(model_cls: type[BaseModel], var: Any) -> 
dict[str, Any]:
-                try:
-                    return 
model_cls.model_validate(var).model_dump(mode="json")  # type: 
ignore[attr-defined]
-                except AttributeError:  # Pydantic 1.x compatibility.
-                    return model_cls.from_orm(var).dict()  # type: 
ignore[attr-defined]
+                return model_cls.model_validate(var).model_dump(mode="json")  
# type: ignore[attr-defined]
 
             if isinstance(var, Job):
                 return cls._encode(_pydantic_model_dump(JobPydantic, var), 
type_=DAT.BASE_JOB)
diff --git a/setup.cfg b/setup.cfg
index 1bbf5fb8f1..cfde203f43 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -133,11 +133,7 @@ install_requires =
     pendulum>=2.0,<3.0
     pluggy>=1.0
     psutil>=4.2.0
-    # We should bump it to at least pydantic>=2.3.0 when we prepare Airflow 
2.8.0 release
-    # we keep Pydantic < 1 for compatibility with packages that depend on 
Pydantic 1
-    # We should also remove then `filterwarning` for pydantic from 
airflow/configuration.py
-    # and # Pydantic v1 check in airflow/serialization/serde.py
-    pydantic>=1.10.0
+    pydantic>=2.3.0
     pygments>=2.0.1
     pyjwt>=2.0.0
     python-daemon>=3.0.0

Reply via email to