diff --git a/elementary/clients/dbt/slim_dbt_runner.py b/elementary/clients/dbt/slim_dbt_runner.py index 10aad54cf..70bf5abf6 100644 --- a/elementary/clients/dbt/slim_dbt_runner.py +++ b/elementary/clients/dbt/slim_dbt_runner.py @@ -17,7 +17,7 @@ from dbt.parser.manifest import ManifestLoader from dbt.tracking import disable_tracking from dbt.version import __version__ as dbt_version_string -from pydantic import BaseModel, validator +from pydantic import BaseModel, field_validator from elementary.clients.dbt.base_dbt_runner import BaseDbtRunner from elementary.utils.log import get_logger @@ -65,7 +65,7 @@ class ConfigArgs(BaseModel): threads: Optional[int] = 1 vars: Optional[Union[str, Dict[str, Any]]] = DEFAULT_VARS - @validator("vars", pre=True) + @field_validator("vars", mode="before") def validate_vars(cls, vars): if not vars: return DEFAULT_VARS diff --git a/elementary/clients/slack/schema.py b/elementary/clients/slack/schema.py index 3f5c47e5c..fe4375117 100644 --- a/elementary/clients/slack/schema.py +++ b/elementary/clients/slack/schema.py @@ -1,6 +1,6 @@ from typing import List, Optional -from pydantic import BaseModel, validator +from pydantic import BaseModel, field_validator from elementary.utils.log import get_logger @@ -17,7 +17,7 @@ class SlackMessageSchema(BaseModel): attachments: Optional[list] = None blocks: Optional[list] = None - @validator("attachments", pre=True) + @field_validator("attachments", mode="before") def validate_attachments(cls, attachments): if ( isinstance(attachments, list) diff --git a/elementary/monitor/api/filters/schema.py b/elementary/monitor/api/filters/schema.py index a24d2eddb..caaf8a487 100644 --- a/elementary/monitor/api/filters/schema.py +++ b/elementary/monitor/api/filters/schema.py @@ -1,9 +1,11 @@ from typing import List, Optional -from pydantic import BaseModel +from pydantic import BaseModel, ConfigDict class FilterSchema(BaseModel): + model_config = ConfigDict(protected_namespaces=()) + name: str display_name: str model_unique_ids: List[Optional[str]] = [] @@ -14,6 +16,8 @@ def add_model_unique_id(self, model_unique_id: Optional[str]): class FiltersSchema(BaseModel): + model_config = ConfigDict(protected_namespaces=()) + test_results: List[FilterSchema] = list() test_runs: List[FilterSchema] = list() model_runs: List[FilterSchema] = list() diff --git a/elementary/monitor/api/groups/schema.py b/elementary/monitor/api/groups/schema.py index 22b3df5e1..363c2fca5 100644 --- a/elementary/monitor/api/groups/schema.py +++ b/elementary/monitor/api/groups/schema.py @@ -4,8 +4,8 @@ class GroupItemSchema(BaseModel): - node_id: Optional[str] - resource_type: Optional[str] + node_id: Optional[str] = None + resource_type: Optional[str] = None DbtGroupSchema = Dict[str, dict] diff --git a/elementary/monitor/api/lineage/schema.py b/elementary/monitor/api/lineage/schema.py index 0432850dd..28aab1375 100644 --- a/elementary/monitor/api/lineage/schema.py +++ b/elementary/monitor/api/lineage/schema.py @@ -1,8 +1,7 @@ -from typing import List, Optional, Tuple +from typing import List, Literal, Optional, Tuple import networkx as nx -from pydantic import BaseModel, validator -from pydantic.typing import Literal +from pydantic import BaseModel, field_validator NodeUniqueIdType = str NodeType = Literal["model", "source", "exposure"] @@ -17,11 +16,11 @@ class LineageSchema(BaseModel): nodes: Optional[List[LineageNodeSchema]] = None edges: Optional[List[Tuple[NodeUniqueIdType, NodeUniqueIdType]]] = None - @validator("nodes", pre=True, always=True) + @field_validator("nodes", mode="before") def set_nodes(cls, nodes): return nodes or [] - @validator("edges", pre=True, always=True) + @field_validator("edges", mode="before") def set_edges(cls, edges): return edges or [] diff --git a/elementary/monitor/api/models/models.py b/elementary/monitor/api/models/models.py index c814ba85e..38f3bf3a1 100644 --- a/elementary/monitor/api/models/models.py +++ b/elementary/monitor/api/models/models.py @@ -1,4 +1,3 @@ -import json import os import statistics from collections import defaultdict @@ -203,7 +202,7 @@ def _normalize_dbt_artifact_dict( SourceSchema: NormalizedSourceSchema, } artifact_name = artifact.name - normalized_artifact = json.loads(artifact.json()) + normalized_artifact = artifact.model_dump() normalized_artifact["model_name"] = artifact_name normalized_artifact["normalized_full_path"] = self._normalize_artifact_path( artifact diff --git a/elementary/monitor/api/models/schema.py b/elementary/monitor/api/models/schema.py index 5d381be3e..92fccde5a 100644 --- a/elementary/monitor/api/models/schema.py +++ b/elementary/monitor/api/models/schema.py @@ -1,8 +1,8 @@ import os import posixpath -from typing import Dict, List, Optional +from typing import Dict, List, Literal, Optional -from pydantic import BaseModel, Field, validator +from pydantic import BaseModel, ConfigDict, Field, field_validator from elementary.monitor.api.totals_schema import TotalsSchema from elementary.monitor.fetchers.models.schema import ( @@ -15,6 +15,8 @@ class NormalizedArtifactSchema(ExtendedBaseModel): + model_config = ConfigDict(protected_namespaces=()) + owners: Optional[List[str]] = [] tags: Optional[List[str]] = [] # Should be changed to artifact_name. @@ -23,32 +25,32 @@ class NormalizedArtifactSchema(ExtendedBaseModel): normalized_full_path: str fqn: str - @validator("tags", pre=True) + @field_validator("tags", mode="before") def load_tags(cls, tags): return cls._load_var_to_list(tags) - @validator("owners", pre=True) + @field_validator("owners", mode="before") def load_owners(cls, owners): return cls._load_var_to_list(owners) - @validator("normalized_full_path", pre=True) + @field_validator("normalized_full_path", mode="before") def format_normalized_full_path_sep(cls, normalized_full_path: str) -> str: return posixpath.sep.join(normalized_full_path.split(os.path.sep)) # NormalizedArtifactSchema must be first in the inheritance order class NormalizedModelSchema(NormalizedArtifactSchema, ModelSchema): - artifact_type: str = Field("model", const=True) + artifact_type: Literal["model"] = "model" # NormalizedArtifactSchema must be first in the inheritance order class NormalizedSourceSchema(NormalizedArtifactSchema, SourceSchema): - artifact_type: str = Field("source", const=True) + artifact_type: Literal["source"] = "source" # NormalizedArtifactSchema must be first in the inheritance order class NormalizedExposureSchema(NormalizedArtifactSchema, ExposureSchema): - artifact_type: str = Field("exposure", const=True) + artifact_type: Literal["exposure"] = "exposure" class ModelCoverageSchema(BaseModel): @@ -60,11 +62,11 @@ class ModelRunSchema(BaseModel): id: str time_utc: str status: str - full_refresh: Optional[bool] - materialization: Optional[str] + full_refresh: Optional[bool] = None + materialization: Optional[str] = None execution_time: float - @validator("time_utc", pre=True) + @field_validator("time_utc", mode="before") def format_time_utc(cls, time_utc): return convert_partial_iso_format_to_full_iso_format(time_utc) diff --git a/elementary/monitor/api/report/report.py b/elementary/monitor/api/report/report.py index 5f9f50889..8cf6f206c 100644 --- a/elementary/monitor/api/report/report.py +++ b/elementary/monitor/api/report/report.py @@ -71,10 +71,10 @@ def get_report_data( test_results.totals, test_runs.totals, models, sources, models_runs.runs ) - serializable_groups = groups.dict() + serializable_groups = groups.model_dump() serializable_models = self._serialize_models(models, sources, exposures) serializable_model_runs = self._serialize_models_runs(models_runs.runs) - serializable_model_runs_totals = models_runs.dict(include={"totals"})[ + serializable_model_runs_totals = models_runs.model_dump(include={"totals"})[ "totals" ] serializable_models_coverages = self._serialize_coverages(coverages) @@ -86,9 +86,9 @@ def get_report_data( ) serializable_test_runs = self._serialize_test_runs(test_runs.runs) serializable_test_runs_totals = self._serialize_totals(test_runs.totals) - serializable_invocation = test_results.invocation.dict() - serializable_filters = filters.dict() - serializable_lineage = lineage.dict() + serializable_invocation = test_results.invocation.model_dump() + serializable_filters = filters.model_dump() + serializable_lineage = lineage.model_dump() models_latest_invocation = invocations_api.get_models_latest_invocation() invocations = invocations_api.get_models_latest_invocations_data() @@ -143,7 +143,7 @@ def _serialize_coverages( return {model_id: dict(coverage) for model_id, coverage in coverages.items()} def _serialize_models_runs(self, models_runs: List[ModelRunsSchema]) -> List[dict]: - return [model_runs.dict(by_alias=True) for model_runs in models_runs] + return [model_runs.model_dump(by_alias=True) for model_runs in models_runs] def _serialize_test_results( self, test_results: Dict[Optional[str], List[TestResultSchema]] @@ -151,7 +151,7 @@ def _serialize_test_results( serializable_test_results = defaultdict(list) for model_unique_id, test_result in test_results.items(): serializable_test_results[model_unique_id].extend( - [result.dict() for result in test_result] + [result.model_dump() for result in test_result] ) return serializable_test_results @@ -161,7 +161,7 @@ def _serialize_test_runs( serializable_test_runs = defaultdict(list) for model_unique_id, test_run in test_runs.items(): serializable_test_runs[model_unique_id].extend( - [run.dict() for run in test_run] + [run.model_dump() for run in test_run] ) return serializable_test_runs @@ -170,5 +170,5 @@ def _serialize_totals( ) -> Dict[Optional[str], dict]: serialized_totals = dict() for model_unique_id, total in totals.items(): - serialized_totals[model_unique_id] = total.dict() + serialized_totals[model_unique_id] = total.model_dump() return serialized_totals diff --git a/elementary/monitor/api/report/schema.py b/elementary/monitor/api/report/schema.py index bd447bc1b..36b4e276c 100644 --- a/elementary/monitor/api/report/schema.py +++ b/elementary/monitor/api/report/schema.py @@ -1,6 +1,6 @@ from typing import Optional -from pydantic import BaseModel +from pydantic import BaseModel, ConfigDict class ReportDataEnvSchema(BaseModel): @@ -10,6 +10,8 @@ class ReportDataEnvSchema(BaseModel): class ReportDataSchema(BaseModel): + model_config = ConfigDict(protected_namespaces=()) + creation_time: Optional[str] = None days_back: Optional[int] = None models: dict = dict() diff --git a/elementary/monitor/api/test_management/test_management.py b/elementary/monitor/api/test_management/test_management.py index b8b24be30..82a9b24fe 100644 --- a/elementary/monitor/api/test_management/test_management.py +++ b/elementary/monitor/api/test_management/test_management.py @@ -16,6 +16,8 @@ class TestManagementAPI(APIClient): + __test__ = False + def __init__( self, dbt_runner: BaseDbtRunner, diff --git a/elementary/monitor/api/tests/schema.py b/elementary/monitor/api/tests/schema.py index ca60615ae..5194dfc54 100644 --- a/elementary/monitor/api/tests/schema.py +++ b/elementary/monitor/api/tests/schema.py @@ -1,6 +1,6 @@ from typing import Dict, List, Optional, Union -from pydantic import BaseModel, Field, validator +from pydantic import BaseModel, ConfigDict, Field, field_validator from elementary.monitor.api.totals_schema import TotalsSchema from elementary.monitor.fetchers.invocations.schema import DbtInvocationSchema @@ -12,9 +12,6 @@ class ElementaryTestResultSchema(BaseModel): metrics: Optional[Union[list, dict]] = None result_description: Optional[str] = None - class Config: - smart_union = True - class DbtTestResultSchema(BaseModel): display_name: Optional[str] = None @@ -24,12 +21,12 @@ class DbtTestResultSchema(BaseModel): class InvocationSchema(BaseModel): - affected_rows: Optional[int] + affected_rows: Optional[int] = None time_utc: str id: str status: str - @validator("time_utc", pre=True) + @field_validator("time_utc", mode="before") def format_time_utc(cls, time_utc): return convert_partial_iso_format_to_full_iso_format(time_utc) @@ -42,6 +39,8 @@ class InvocationsSchema(BaseModel): class TestMetadataSchema(BaseModel): + model_config = ConfigDict(protected_namespaces=()) + test_unique_id: str elementary_unique_id: str database_name: Optional[str] = None @@ -69,9 +68,6 @@ class TestResultSchema(BaseModel): metadata: TestMetadataSchema test_results: Union[DbtTestResultSchema, ElementaryTestResultSchema] - class Config: - smart_union = True - class TestResultsWithTotalsSchema(BaseModel): results: Dict[Optional[str], List[TestResultSchema]] = dict() @@ -81,7 +77,7 @@ class TestResultsWithTotalsSchema(BaseModel): class TestRunSchema(BaseModel): metadata: TestMetadataSchema - test_runs: Optional[InvocationsSchema] + test_runs: Optional[InvocationsSchema] = None class TestRunsWithTotalsSchema(BaseModel): diff --git a/elementary/monitor/data_monitoring/data_monitoring.py b/elementary/monitor/data_monitoring/data_monitoring.py index b5b6a8110..0e530895a 100644 --- a/elementary/monitor/data_monitoring/data_monitoring.py +++ b/elementary/monitor/data_monitoring/data_monitoring.py @@ -47,7 +47,7 @@ def __init__( tracking.register_group( "warehouse", self.warehouse_info.id, - self.warehouse_info.dict(), + self.warehouse_info.model_dump(), ) tracking.set_env("target_name", latest_invocation.get("target_name")) tracking.set_env("dbt_orchestrator", latest_invocation.get("orchestrator")) diff --git a/elementary/monitor/data_monitoring/report/data_monitoring_report.py b/elementary/monitor/data_monitoring/report/data_monitoring_report.py index 3bf18d08b..eb8b2d915 100644 --- a/elementary/monitor/data_monitoring/report/data_monitoring_report.py +++ b/elementary/monitor/data_monitoring/report/data_monitoring_report.py @@ -125,7 +125,7 @@ def get_report_data( ) self.success = False - report_data_dict = report_data.dict() + report_data_dict = report_data.model_dump() return report_data_dict def _add_report_tracking( diff --git a/elementary/monitor/data_monitoring/schema.py b/elementary/monitor/data_monitoring/schema.py index 168fc76a0..a7c5cb15d 100644 --- a/elementary/monitor/data_monitoring/schema.py +++ b/elementary/monitor/data_monitoring/schema.py @@ -2,7 +2,7 @@ from enum import Enum from typing import Dict, List, Optional -from pydantic import BaseModel, validator +from pydantic import BaseModel, field_validator from elementary.monitor.alerts.model import ModelAlert from elementary.monitor.alerts.source_freshness import SourceFreshnessAlert @@ -62,7 +62,7 @@ class SelectorFilterSchema(BaseModel): resource_types: Optional[List[ResourceType]] = None node_names: Optional[List[str]] = None - @validator("invocation_time", pre=True) + @field_validator("invocation_time", mode="before") def format_invocation_time(cls, invocation_time): if invocation_time: try: diff --git a/elementary/monitor/fetchers/invocations/schema.py b/elementary/monitor/fetchers/invocations/schema.py index 7b8d3c93b..d7caaf1f7 100644 --- a/elementary/monitor/fetchers/invocations/schema.py +++ b/elementary/monitor/fetchers/invocations/schema.py @@ -1,6 +1,6 @@ from typing import Optional -from pydantic import BaseModel, validator +from pydantic import BaseModel, field_validator from elementary.utils.json_utils import try_load_json from elementary.utils.time import convert_partial_iso_format_to_full_iso_format @@ -17,11 +17,11 @@ class DbtInvocationSchema(BaseModel): job_id: Optional[str] = None orchestrator: Optional[str] = None - @validator("detected_at", pre=True) + @field_validator("detected_at", mode="before") def format_detected_at(cls, detected_at): return convert_partial_iso_format_to_full_iso_format(detected_at) - @validator("selected", pre=True) + @field_validator("selected", mode="before") def format_selected(cls, selected): selected_list = try_load_json(selected) or [] return " ".join(selected_list) diff --git a/elementary/monitor/fetchers/lineage/schema.py b/elementary/monitor/fetchers/lineage/schema.py index 65239b614..2a83625a2 100644 --- a/elementary/monitor/fetchers/lineage/schema.py +++ b/elementary/monitor/fetchers/lineage/schema.py @@ -1,8 +1,7 @@ import re -from typing import List, Optional +from typing import List, Literal, Optional -from pydantic import BaseModel, validator -from pydantic.typing import Literal +from pydantic import BaseModel, field_validator SEED_PATH_PATTERN = re.compile(r"^seed\.") @@ -15,7 +14,7 @@ class NodeDependsOnNodesSchema(BaseModel): depends_on_nodes: Optional[List[NodeUniqueIdType]] = None type: NodeType - @validator("depends_on_nodes", pre=True, always=True) + @field_validator("depends_on_nodes", mode="before") def set_depends_on_nodes(cls, depends_on_nodes): formatted_depends_on = depends_on_nodes or [] formatted_depends_on = [ diff --git a/elementary/monitor/fetchers/models/schema.py b/elementary/monitor/fetchers/models/schema.py index 7626d4f84..50e7310dc 100644 --- a/elementary/monitor/fetchers/models/schema.py +++ b/elementary/monitor/fetchers/models/schema.py @@ -2,7 +2,7 @@ import posixpath from typing import Any, Dict, List, Optional, TypeVar -from pydantic import Field, validator +from pydantic import ConfigDict, Field, field_validator from elementary.utils.schema import ExtendedBaseModel from elementary.utils.time import convert_partial_iso_format_to_full_iso_format @@ -19,7 +19,7 @@ class ModelRunSchema(ExtendedBaseModel): materialization: Optional[str] = None generated_at: str - @validator("generated_at", pre=True) + @field_validator("generated_at", mode="before") def format_generated_at(cls, generated_at): return convert_partial_iso_format_to_full_iso_format(generated_at) @@ -34,19 +34,19 @@ class ArtifactSchema(ExtendedBaseModel): full_path: Optional[str] = None meta: Optional[Dict[str, Any]] = None - @validator("tags", pre=True) + @field_validator("tags", mode="before") def load_tags(cls, tags): return cls._load_var_to_list(tags) - @validator("owners", pre=True) + @field_validator("owners", mode="before") def load_owners(cls, owners): return cls._load_var_to_list(owners) - @validator("full_path", pre=True) + @field_validator("full_path", mode="before") def format_full_path_sep(cls, full_path: str) -> str: return posixpath.sep.join(full_path.split(os.path.sep)) - @validator("meta", pre=True) + @field_validator("meta", mode="before") def load_meta(cls, meta): return cls._load_var_to_dict(meta) @@ -88,6 +88,8 @@ class ExposureSchema(ArtifactSchema): class ModelTestCoverage(ExtendedBaseModel): + model_config = ConfigDict(protected_namespaces=()) + model_unique_id: Optional[str] = None column_tests: int = 0 table_tests: int = 0 diff --git a/elementary/monitor/fetchers/test_management/schema.py b/elementary/monitor/fetchers/test_management/schema.py index 27095b3a2..9bf48be40 100644 --- a/elementary/monitor/fetchers/test_management/schema.py +++ b/elementary/monitor/fetchers/test_management/schema.py @@ -1,6 +1,6 @@ from typing import List, Literal, Optional -from pydantic import BaseModel, Field, validator +from pydantic import BaseModel, ConfigDict, Field, field_validator from elementary.utils.time import convert_partial_iso_format_to_full_iso_format @@ -26,6 +26,9 @@ class ResourcesModel(BaseModel): class TestModel(BaseModel): + __test__ = False + model_config = ConfigDict(protected_namespaces=()) + id: str db_schema: str = Field(alias="schema") table: Optional[str] = None @@ -41,24 +44,25 @@ class TestModel(BaseModel): tags: List[str] = Field(default_factory=list) model_tags: List[str] = Field(default_factory=list) meta: dict = Field(default_factory=dict) - description: Optional[str] + description: Optional[str] = None is_singular: bool updated_at: str updated_by: Optional[str] = None - @validator("severity", pre=True) + @field_validator("severity", mode="before") def validate_severity(cls, severity: str) -> str: severity_lower_string = severity.lower() if severity_lower_string not in ["error", "warn"]: raise ValueError('Severity must be "warn" or "error"') return severity_lower_string - @validator("updated_at", pre=True) + @field_validator("updated_at", mode="before") def validate_updated_at(cls, updated_at: str) -> str: return convert_partial_iso_format_to_full_iso_format(updated_at) class TestsModel(BaseModel): + __test__ = False tests: List[TestModel] = Field(default_factory=list) diff --git a/elementary/monitor/fetchers/test_management/test_management.py b/elementary/monitor/fetchers/test_management/test_management.py index 7c1048148..6a4bac22c 100644 --- a/elementary/monitor/fetchers/test_management/test_management.py +++ b/elementary/monitor/fetchers/test_management/test_management.py @@ -18,6 +18,8 @@ class TestManagementFetcher(FetcherClient): + __test__ = False + def __init__(self, dbt_runner: BaseDbtRunner): super().__init__(dbt_runner) diff --git a/elementary/monitor/fetchers/tests/schema.py b/elementary/monitor/fetchers/tests/schema.py index 289e88cb7..047adb0d7 100644 --- a/elementary/monitor/fetchers/tests/schema.py +++ b/elementary/monitor/fetchers/tests/schema.py @@ -1,6 +1,6 @@ from typing import List, Optional, Union -from pydantic import validator +from pydantic import ConfigDict, FieldValidationInfo, field_validator from elementary.utils.schema import ExtendedBaseModel from elementary.utils.time import convert_partial_iso_format_to_full_iso_format @@ -8,6 +8,7 @@ class TestResultDBRowSchema(ExtendedBaseModel): __test__ = False # Mark for pytest - The class name starts with "Test" which throws warnings on pytest runs + model_config = ConfigDict(protected_namespaces=()) id: str invocation_id: Optional[str] = None @@ -19,17 +20,17 @@ class TestResultDBRowSchema(ExtendedBaseModel): database_name: Optional[str] = None schema_name: str table_name: Optional[str] = None - column_name: Optional[str] + column_name: Optional[str] = None test_type: str test_sub_type: str - test_results_description: Optional[str] - owners: Optional[List[str]] - model_owner: Optional[List[str]] - tags: Optional[List[str]] + test_results_description: Optional[str] = None + owners: Optional[List[str]] = None + model_owner: Optional[List[str]] = None + tags: Optional[List[str]] = None meta: dict model_meta: dict test_results_query: Optional[str] = None - other: Optional[str] + other: Optional[str] = None test_name: str test_params: dict severity: str @@ -40,43 +41,40 @@ class TestResultDBRowSchema(ExtendedBaseModel): sample_data: Optional[Union[dict, List]] = None failures: Optional[int] = None - class Config: - smart_union = True - - @validator("detected_at", pre=True) + @field_validator("detected_at", mode="before") def format_detected_at(cls, detected_at): return convert_partial_iso_format_to_full_iso_format(detected_at) - @validator("meta", pre=True) + @field_validator("meta", mode="before") def load_meta(cls, meta): return cls._load_var_to_dict(meta) - @validator("model_meta", pre=True) + @field_validator("model_meta", mode="before") def load_model_meta(cls, model_meta): return cls._load_var_to_dict(model_meta) - @validator("test_params", pre=True) + @field_validator("test_params", mode="before") def load_test_params(cls, test_params): return cls._load_var_to_dict(test_params) - @validator("test_results_description", pre=True) + @field_validator("test_results_description", mode="before") def load_test_results_description(cls, test_results_description): return test_results_description.strip() if test_results_description else None - @validator("tags", pre=True) + @field_validator("tags", mode="before") def load_tags(cls, tags): return cls._load_var_to_list(tags) - @validator("owners", pre=True) + @field_validator("owners", mode="before") def load_owners(cls, owners): return cls._load_var_to_list(owners) - @validator("model_owner", pre=True) + @field_validator("model_owner", mode="before") def load_model_owner(cls, model_owner): return cls._load_var_to_list(model_owner) - @validator("failures", pre=True) - def parse_failures(cls, failures, values): - test_type = values.get("test_type") + @field_validator("failures", mode="before") + def parse_failures(cls, failures, info: FieldValidationInfo): + test_type = info.data.get("test_type") # Elementary's tests doesn't return correct failures. return failures or None if test_type == "dbt_test" else None diff --git a/elementary/utils/schema.py b/elementary/utils/schema.py index f82903e8d..92da0d0b2 100644 --- a/elementary/utils/schema.py +++ b/elementary/utils/schema.py @@ -1,12 +1,14 @@ import json from typing import Union -from pydantic import BaseModel +from pydantic import BaseModel, ConfigDict from elementary.utils.json_utils import try_load_json class ExtendedBaseModel(BaseModel): + model_config = ConfigDict(protected_namespaces=()) + @staticmethod def _load_var_to_dict(var: Union[str, dict]) -> dict: if not var: diff --git a/pyproject.toml b/pyproject.toml index 87cd6901a..acf8275be 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ google-cloud-storage = "<3.0.0" alive-progress = "<=2.3.1" slack-sdk = ">=3.20.1,<4.0.0" pytest-parametrization = ">=2022.2.1" -pydantic = "<2.0" +pydantic = ">=2.0,<3" networkx = ">=2.3,<3" packaging = ">=20.9,<=23.1" azure-storage-blob = ">=12.11.0" diff --git a/tests/unit/clients/slack/test_slack_message_builder.py b/tests/unit/clients/slack/test_slack_message_builder.py index 6d02f83fe..35c19509e 100644 --- a/tests/unit/clients/slack/test_slack_message_builder.py +++ b/tests/unit/clients/slack/test_slack_message_builder.py @@ -228,7 +228,7 @@ def test_get_slack_message(): slack_message_builder = SlackMessageBuilder() slack_message = slack_message_builder.get_slack_message() assert isinstance(slack_message, SlackMessageSchema) - assert json.dumps(slack_message.dict(), sort_keys=True) == json.dumps( + assert json.dumps(slack_message.model_dump(), sort_keys=True) == json.dumps( {"blocks": [], "attachments": [{"blocks": []}], "text": None}, sort_keys=True ) @@ -240,7 +240,7 @@ def test_add_blocks_as_attachments(): slack_message_builder._add_blocks_as_attachments([first_block]) slack_message_builder._add_blocks_as_attachments([second_block]) slack_message = slack_message_builder.get_slack_message() - assert json.dumps(slack_message.dict(), sort_keys=True) == json.dumps( + assert json.dumps(slack_message.model_dump(), sort_keys=True) == json.dumps( { "blocks": [], "attachments": [ @@ -270,7 +270,7 @@ def test_add_always_displayed_blocks(): slack_message_builder._add_always_displayed_blocks([first_block]) slack_message_builder._add_always_displayed_blocks([second_block]) slack_message = slack_message_builder.get_slack_message() - assert json.dumps(slack_message.dict(), sort_keys=True) == json.dumps( + assert json.dumps(slack_message.model_dump(), sort_keys=True) == json.dumps( { "blocks": [ {"type": "divider"},