diff --git a/cg/models/analysis.py b/cg/models/analysis.py index c2e3eb8b80..348a91aa59 100644 --- a/cg/models/analysis.py +++ b/cg/models/analysis.py @@ -1,4 +1,4 @@ -from pydantic import BaseModel, ConfigDict +from pydantic.v1 import BaseModel from cg.models.raredisease.raredisease import RarediseaseQCMetrics from cg.models.rnafusion.rnafusion import RnafusionQCMetrics @@ -9,7 +9,8 @@ class AnalysisModel(BaseModel): """Metadata analysis model""" - model_config = ConfigDict(arbitrary_types_allowed=True) + class Config: + arbitrary_types_allowed = True class NextflowAnalysis(AnalysisModel): diff --git a/cg/models/balsamic/config.py b/cg/models/balsamic/config.py index 233c056c42..82998e41ea 100644 --- a/cg/models/balsamic/config.py +++ b/cg/models/balsamic/config.py @@ -1,7 +1,7 @@ from datetime import datetime from pathlib import Path -from pydantic import BaseModel, field_validator, ValidationInfo +from pydantic.v1 import BaseModel, validator from cg.constants.constants import SampleType @@ -47,17 +47,16 @@ class BalsamicConfigReference(BaseModel): """ reference_genome: Path - reference_genome_version: str | None = None + reference_genome_version: str | None - @field_validator("reference_genome_version") - @classmethod - def extract_genome_version_from_path(cls, _, info: ValidationInfo) -> str: + @validator("reference_genome_version", always=True) + def extract_genome_version_from_path(cls, value: str | None, values: dict) -> str: """ Return the genome version from the reference path: /home/proj/stage/cancer/balsamic_cache/X.X.X/hg19/genome/human_g1k_v37.fasta """ - return str(info.data.get("reference_genome")).split("/")[-3] + return str(values["reference_genome"]).split("/")[-3] class BalsamicConfigPanel(BaseModel): @@ -71,24 +70,23 @@ class BalsamicConfigPanel(BaseModel): """ capture_kit: str - capture_kit_version: str | None = None + capture_kit_version: str | None chrom: list[str] pon_cnn: str | None = None - @field_validator("capture_kit", mode="before") - @classmethod + @validator("capture_kit", pre=True) def get_filename_from_path(cls, path: str) -> str: """Return the base name of the provided file path.""" return Path(path).name - @field_validator("capture_kit_version") - @classmethod - def get_panel_version_from_filename(cls, _, info: ValidationInfo) -> str: + @validator("capture_kit_version", always=True) + def get_panel_version_from_filename( + cls, capture_kit_version: str | None, values: dict[str, str | None] + ) -> str: """Return the panel bed version from its filename (e.g. gicfdna_3.1_hg19_design.bed).""" - return info.data.get("capture_kit").split("_")[-3] + return values["capture_kit"].split("_")[-3] - @field_validator("pon_cnn", mode="before") - @classmethod + @validator("pon_cnn", pre=True) def get_pon_cnn_name_version_from_filename(cls, pon_cnn: str | None) -> str: """Return the CNVkit PON name and version from its filename (gmsmyeloid_5.3_hg19_design_CNVkit_PON_reference_v1.cnn).""" pon_cnn_filename_split: list[str] = Path(pon_cnn).stem.split("_") @@ -112,12 +110,12 @@ class BalsamicConfigQC(BaseModel): """ picard_rmdup: bool - adapter: str | None = None + adapter: str | None quality_trim: bool adapter_trim: bool umi_trim: bool - min_seq_length: str | None = None - umi_trim_length: str | None = None + min_seq_length: str | None + umi_trim_length: str | None class BalsamicVarCaller(BaseModel): @@ -151,7 +149,7 @@ class BalsamicConfigJSON(BaseModel): analysis: BalsamicConfigAnalysis samples: list[BalsamicConfigSample] reference: BalsamicConfigReference - panel: BalsamicConfigPanel | None = None + panel: BalsamicConfigPanel | None QC: BalsamicConfigQC vcf: dict[str, BalsamicVarCaller] bioinfo_tools_version: dict[str, list[str]] diff --git a/cg/models/balsamic/metrics.py b/cg/models/balsamic/metrics.py index c45ece2906..bbf91d1e49 100644 --- a/cg/models/balsamic/metrics.py +++ b/cg/models/balsamic/metrics.py @@ -1,4 +1,4 @@ -from pydantic import field_validator +from pydantic.v1 import validator from cg.models.deliverables.metric_deliverables import MetricCondition, MetricsBase from cg.models.qc_metrics import QCMetrics @@ -17,56 +17,60 @@ class BalsamicMetricsBase(MetricsBase): condition: balsamic metric validation condition """ - condition: MetricCondition | None = None + condition: MetricCondition | None class BalsamicQCMetrics(QCMetrics): """BALSAMIC common QC metrics""" - fold_80_base_penalty: float | None = None - mean_insert_size: float | None = None - percent_duplication: float | None = None + fold_80_base_penalty: float | None + mean_insert_size: float | None + percent_duplication: float | None - _percent_duplication: float = field_validator("percent_duplication")(percent_value_validation) + _percent_duplication = validator("percent_duplication", allow_reuse=True)( + percent_value_validation + ) class BalsamicTargetedQCMetrics(BalsamicQCMetrics): """BALSAMIC targeted QC metrics""" - mean_target_coverage: float | None = None - median_target_coverage: float | None = None - pct_target_bases_50x: float | None = None - pct_target_bases_100x: float | None = None - pct_target_bases_250x: float | None = None - pct_target_bases_500x: float | None = None - pct_target_bases_1000x: float | None = None - pct_off_bait: float | None = None - gc_dropout: float | None = None - - _pct_values: float = field_validator( + mean_target_coverage: float | None + median_target_coverage: float | None + pct_target_bases_50x: float | None + pct_target_bases_100x: float | None + pct_target_bases_250x: float | None + pct_target_bases_500x: float | None + pct_target_bases_1000x: float | None + pct_off_bait: float | None + gc_dropout: float | None + + _pct_values = validator( "pct_target_bases_50x", "pct_target_bases_100x", "pct_target_bases_250x", "pct_target_bases_500x", "pct_target_bases_1000x", "pct_off_bait", + allow_reuse=True, )(percent_value_validation) class BalsamicWGSQCMetrics(BalsamicQCMetrics): """BALSAMIC WGS QC metrics""" - median_coverage: float | None = None - pct_15x: float | None = None - pct_30x: float | None = None - pct_60x: float | None = None - pct_100x: float | None = None - pct_pf_reads_improper_pairs: float | None = None + median_coverage: float | None + pct_15x: float | None + pct_30x: float | None + pct_60x: float | None + pct_100x: float | None + pct_pf_reads_improper_pairs: float | None - _pct_values: float = field_validator( + _pct_values = validator( "pct_15x", "pct_30x", "pct_60x", "pct_100x", "pct_pf_reads_improper_pairs", + allow_reuse=True, )(percent_value_validation) diff --git a/cg/models/deliverables/metric_deliverables.py b/cg/models/deliverables/metric_deliverables.py index 1d2ad7f849..43e60b561a 100644 --- a/cg/models/deliverables/metric_deliverables.py +++ b/cg/models/deliverables/metric_deliverables.py @@ -1,7 +1,8 @@ import operator from typing import Annotated, Any, Callable -from pydantic import BaseModel, Field, ValidationInfo, field_validator +from pydantic import BaseModel, Field, field_validator +from pydantic_core.core_schema import ValidationInfo from cg.constants import PRECISION from cg.exc import CgError, MetricsQCError diff --git a/cg/models/delivery_report/metadata.py b/cg/models/delivery_report/metadata.py index f18e0945fe..b8c3368b2b 100644 --- a/cg/models/delivery_report/metadata.py +++ b/cg/models/delivery_report/metadata.py @@ -151,7 +151,6 @@ class WTSSampleMetadataModel(SequencingSampleMetadataModel): uniquely_mapped_reads: Annotated[str, BeforeValidator(get_number_as_string)] = NA_FIELD @field_validator("rin") - @classmethod def ensure_rin_thresholds(cls, rin: str) -> str: if rin != NA_FIELD: rin_number = float(rin) diff --git a/cg/models/qc_metrics.py b/cg/models/qc_metrics.py index 0392131879..97ae429e81 100644 --- a/cg/models/qc_metrics.py +++ b/cg/models/qc_metrics.py @@ -1,4 +1,4 @@ -from pydantic import BaseModel +from pydantic.v1 import BaseModel class QCMetrics(BaseModel): diff --git a/tests/meta/workflow/test_rnafusion.py b/tests/meta/workflow/test_rnafusion.py index 5ee071e03d..a6d6931dd8 100644 --- a/tests/meta/workflow/test_rnafusion.py +++ b/tests/meta/workflow/test_rnafusion.py @@ -24,7 +24,7 @@ def test_parse_analysis( analysis_model: NextflowAnalysis = analysis_api.parse_analysis(qc_metrics_raw=qc_metrics) # THEN the analysis model and its content should have been correctly extracted - assert analysis_model.sample_metrics[sample_id].model_dump() == rnafusion_metrics + assert analysis_model.sample_metrics[sample_id] == rnafusion_metrics def test_get_latest_metadata(