From 78982711eb84a70c4740bd2abbd27d6a7998ecfe Mon Sep 17 00:00:00 2001 From: henrikstranneheim Date: Sat, 27 Jul 2024 11:40:47 +0200 Subject: [PATCH 1/6] feat(lims) WIP --- cg/models/lims/sample.py | 95 +++++++++++----------- tests/meta/orders/test_meta_orders_lims.py | 16 ++-- tests/models/lims/conftest.py | 15 ++++ tests/models/lims/test_lims_models.py | 28 +++++++ 4 files changed, 100 insertions(+), 54 deletions(-) create mode 100644 tests/models/lims/conftest.py create mode 100644 tests/models/lims/test_lims_models.py diff --git a/cg/models/lims/sample.py b/cg/models/lims/sample.py index 3fbd784837..c8208cee98 100644 --- a/cg/models/lims/sample.py +++ b/cg/models/lims/sample.py @@ -1,4 +1,6 @@ -from pydantic.v1 import BaseModel, validator +from typing import Annotated + +from pydantic import BaseModel, Field, field_validator from typing_extensions import Literal from cg.constants import Priority @@ -8,65 +10,66 @@ class Udf(BaseModel): application: str - capture_kit: str | None - collection_date: str | None - comment: str | None - concentration: str | None - concentration_sample: str | None - concentration_ng_ul: str | None + capture_kit: str | None = None + collection_date: str | None = None + comment: str | None = None + concentration: float | None = None + concentration_ng_ul: str | None = None + concentration_sample: float | None = None + control: str | None = None customer: str - control: str | None - data_analysis: str | None - data_delivery: str | None - elution_buffer: str | None - extraction_method: str | None + data_analysis: str | None = None + data_delivery: str | None = None + elution_buffer: str | None = None + extraction_method: str | None = None family_name: str | None = "NA" - formalin_fixation_time: str | None - index: str | None - index_number: str | None - lab_code: str | None - organism: str | None - organism_other: str | None - original_lab: str | None - original_lab_address: str | None - pool: str | None - post_formalin_fixation_time: str | None - pre_processing_method: str | None - primer: str | None + formalin_fixation_time: int | None = None + index: str | None = None + index_number: str | None = None + lab_code: str | None = None + organism: str | None = None + organism_other: str | None = None + original_lab: str | None = None + original_lab_address: str | None = None + pool: str | None = None + post_formalin_fixation_time: int | None = None + pre_processing_method: str | None = None + primer: str | None = None priority: str = Priority.standard.name - quantity: str | None - reference_genome: str | None - region: str | None - region_code: str | None + quantity: int | None = None + reference_genome: str | None = None + region: str | None = None + region_code: str | None = None require_qc_ok: bool = False - rml_plate_name: str | None - selection_criteria: str | None - sex: Literal["M", "F", "unknown"] = "unknown" + rml_plate_name: str | None = None + selection_criteria: str | None = None + sex: Annotated[str, Field(validate_default=True)] = "unknown" skip_reception_control: bool | None = None source: str = "NA" - tissue_block_size: str | None + tissue_block_size: str | None = None tumour: bool | None = False - tumour_purity: str | None - volume: str | None - well_position_rml: str | None - verified_organism: bool | None + tumour_purity: int | None = None + verified_organism: bool | None = None + volume: str | None = None + well_position_rml: str | None = None - @validator("sex", pre=True) - def validate_sex(cls, value: str): - return SEX_MAP.get(value, "unknown") + @field_validator("sex", mode="before") + @classmethod + def get_udf_sex(cls, sex: Literal["male", "female", "unknown"]) -> str: + return SEX_MAP.get(sex, "unknown") class LimsSample(BaseModel): name: str container: str = "Tube" - container_name: str | None - well_position: str | None - index_sequence: str | None - udfs: Udf | None + container_name: str | None = None + well_position: str | None = None + index_sequence: str | None = None + udfs: Udf | None = None @classmethod - def parse_obj(cls, obj: dict): - parsed_obj: LimsSample = super().parse_obj(obj) - udf: Udf = Udf.parse_obj(obj) + def parse_obj(cls, sample_raw: dict): + parsed_obj: LimsSample = super().model_validate(sample_raw) + udf: Udf = Udf.model_validate(sample_raw) parsed_obj.udfs = udf return parsed_obj diff --git a/tests/meta/orders/test_meta_orders_lims.py b/tests/meta/orders/test_meta_orders_lims.py index b3c6c3ecaf..5aa0639b36 100644 --- a/tests/meta/orders/test_meta_orders_lims.py +++ b/tests/meta/orders/test_meta_orders_lims.py @@ -30,7 +30,7 @@ def test_to_lims_mip(mip_order_to_submit): assert first_sample.udfs.priority == "standard" assert first_sample.udfs.application == "WGSPCFC030" assert first_sample.udfs.source == "tissue (fresh frozen)" - assert first_sample.udfs.quantity == "220" + assert first_sample.udfs.quantity == 220 assert first_sample.udfs.customer == "cust003" assert first_sample.udfs.volume == "1.0" @@ -68,7 +68,7 @@ def test_to_lims_rml(rml_order_to_submit): first_sample = samples[0] assert first_sample.udfs.pool == "pool-1" assert first_sample.udfs.volume == "30" - assert first_sample.udfs.concentration == "5.0" + assert first_sample.udfs.concentration == 5.0 assert first_sample.udfs.index == "IDT DupSeq 10 bp Set B" assert first_sample.udfs.index_number == "1" @@ -139,7 +139,7 @@ def test_to_lims_balsamic(balsamic_order_to_submit, project): # ... and pick out relevant UDFs first_sample = samples[0].dict() assert first_sample["name"] == "s1" - assert {sample.container for sample in samples} == set(["96 well plate"]) + assert {sample.container for sample in samples} == {"96 well plate"} assert first_sample["udfs"]["data_analysis"] in [ Workflow.BALSAMIC, Workflow.BALSAMIC_QC, @@ -153,15 +153,15 @@ def test_to_lims_balsamic(balsamic_order_to_submit, project): assert first_sample["udfs"]["volume"] == "1.0" assert first_sample["udfs"]["priority"] == "standard" - assert container_names == set(["p1"]) + assert container_names == {"p1"} assert first_sample["well_position"] == "A:1" assert first_sample["udfs"]["tumour"] is True assert first_sample["udfs"]["capture_kit"] == "other" - assert first_sample["udfs"]["tumour_purity"] == "75" + assert first_sample["udfs"]["tumour_purity"] == 75 - assert first_sample["udfs"]["formalin_fixation_time"] == "1" - assert first_sample["udfs"]["post_formalin_fixation_time"] == "2" + assert first_sample["udfs"]["formalin_fixation_time"] == 1 + assert first_sample["udfs"]["post_formalin_fixation_time"] == 2 assert first_sample["udfs"]["tissue_block_size"] == "small" - assert first_sample["udfs"]["quantity"] == "2" + assert first_sample["udfs"]["quantity"] == 2 assert first_sample["udfs"]["comment"] == "other Elution buffer" diff --git a/tests/models/lims/conftest.py b/tests/models/lims/conftest.py new file mode 100644 index 0000000000..386838adec --- /dev/null +++ b/tests/models/lims/conftest.py @@ -0,0 +1,15 @@ +import pytest + +from cg.constants.constants import CustomerId + + +@pytest.fixture +def lims_sample_raw() -> dict[str, str]: + """Return a raw LIMS sample.""" + return {"name": "a_name", "container": "a_tube"} + + +@pytest.fixture +def lims_udfs_raw() -> dict[str, str]: + """Return a raw LIMS uUDF.""" + return {"application": "WGS", "customer": CustomerId.CUST001, "sex": "male"} diff --git a/tests/models/lims/test_lims_models.py b/tests/models/lims/test_lims_models.py new file mode 100644 index 0000000000..4d0b1e87fd --- /dev/null +++ b/tests/models/lims/test_lims_models.py @@ -0,0 +1,28 @@ +from cg.models.lims.sample import LimsSample, Udf + + +def test_instantiate_lims_sample_model(lims_sample_raw: dict[str, str]): + """Tests LIMS sample dict against a LIMS sample pydantic model.""" + + # GIVEN a LIMS sample + + # WHEN instantiating + lims_sample = LimsSample.model_validate(lims_sample_raw) + + # THEN assert that it was successfully created + assert isinstance(lims_sample, LimsSample) + + +def test_instantiate_lims_udf_model(lims_udfs_raw: dict[str, str]): + """Tests LIMS UDFs dict against a LIMS UDF pydantic model.""" + + # GIVEN LIMS UDFs + + # WHEN instantiating + lims_udf = Udf.model_validate(lims_udfs_raw) + + # THEN assert that it was successfully created + assert isinstance(lims_udf, Udf) + + # THEN the sex should be set + assert lims_udf.sex == "M" From 24e956be4d3ca33c67eeba390205d0a537c975ca Mon Sep 17 00:00:00 2001 From: henrikstranneheim Date: Sat, 27 Jul 2024 11:51:14 +0200 Subject: [PATCH 2/6] feat(lims) WIP --- cg/models/lims/sample.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cg/models/lims/sample.py b/cg/models/lims/sample.py index c8208cee98..06b4e2d2ac 100644 --- a/cg/models/lims/sample.py +++ b/cg/models/lims/sample.py @@ -69,7 +69,6 @@ class LimsSample(BaseModel): @classmethod def parse_obj(cls, sample_raw: dict): - parsed_obj: LimsSample = super().model_validate(sample_raw) - udf: Udf = Udf.model_validate(sample_raw) - parsed_obj.udfs = udf - return parsed_obj + lims_sample: LimsSample = super().model_validate(sample_raw) + lims_sample.udfs = Udf.model_validate(sample_raw) + return lims_sample From f3cd59235736ed639513189ace9236e7ce04a25a Mon Sep 17 00:00:00 2001 From: henrikstranneheim Date: Sun, 28 Jul 2024 12:27:34 +0200 Subject: [PATCH 3/6] feat(lims) WIP --- cg/apps/lims/api.py | 9 +++++++-- cg/models/lims/sample.py | 8 ++++++++ tests/models/lims/conftest.py | 8 +++++++- tests/models/lims/test_lims_models.py | 14 +++++++++++++- 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/cg/apps/lims/api.py b/cg/apps/lims/api.py index b8975985ae..85f7a8a38b 100644 --- a/cg/apps/lims/api.py +++ b/cg/apps/lims/api.py @@ -10,7 +10,12 @@ from requests.exceptions import HTTPError from cg.constants import Priority -from cg.constants.lims import MASTER_STEPS_UDFS, PROP2UDF, DocumentationMethod, LimsArtifactTypes +from cg.constants.lims import ( + MASTER_STEPS_UDFS, + PROP2UDF, + DocumentationMethod, + LimsArtifactTypes, +) from cg.exc import LimsDataError from .order import OrderHandler @@ -88,7 +93,7 @@ def _export_sample(self, lims_sample): "project": self._export_project(lims_sample.project), "family": udfs.get("familyID"), "customer": udfs.get("customer"), - "sex": SEX_MAP.get(udfs.get("Gender"), None), + "sex": SEX_MAP.get(udfs.get("Gender")), "father": udfs.get("fatherID"), "mother": udfs.get("motherID"), "source": udfs.get("Source"), diff --git a/cg/models/lims/sample.py b/cg/models/lims/sample.py index 06b4e2d2ac..9de696e780 100644 --- a/cg/models/lims/sample.py +++ b/cg/models/lims/sample.py @@ -1,3 +1,4 @@ +from datetime import datetime from typing import Annotated from pydantic import BaseModel, Field, field_validator @@ -8,6 +9,12 @@ SEX_MAP = {"male": "M", "female": "F"} +class LimsProject(BaseModel): + id: str + name: str + date: datetime | None = None + + class Udf(BaseModel): application: str capture_kit: str | None = None @@ -65,6 +72,7 @@ class LimsSample(BaseModel): container_name: str | None = None well_position: str | None = None index_sequence: str | None = None + project: LimsProject | None = None udfs: Udf | None = None @classmethod diff --git a/tests/models/lims/conftest.py b/tests/models/lims/conftest.py index 386838adec..83183f8278 100644 --- a/tests/models/lims/conftest.py +++ b/tests/models/lims/conftest.py @@ -11,5 +11,11 @@ def lims_sample_raw() -> dict[str, str]: @pytest.fixture def lims_udfs_raw() -> dict[str, str]: - """Return a raw LIMS uUDF.""" + """Return a raw LIMS UDF.""" return {"application": "WGS", "customer": CustomerId.CUST001, "sex": "male"} + + +@pytest.fixture +def lims_project_raw() -> dict[str, str]: + """Return a raw LIMS project.""" + return {"id": "an_id", "name": "a_name", "date": "2000-01-01"} diff --git a/tests/models/lims/test_lims_models.py b/tests/models/lims/test_lims_models.py index 4d0b1e87fd..6496d8dce1 100644 --- a/tests/models/lims/test_lims_models.py +++ b/tests/models/lims/test_lims_models.py @@ -1,4 +1,4 @@ -from cg.models.lims.sample import LimsSample, Udf +from cg.models.lims.sample import LimsProject, LimsSample, Udf def test_instantiate_lims_sample_model(lims_sample_raw: dict[str, str]): @@ -26,3 +26,15 @@ def test_instantiate_lims_udf_model(lims_udfs_raw: dict[str, str]): # THEN the sex should be set assert lims_udf.sex == "M" + + +def test_instantiate_lims_project_model(lims_project_raw: dict[str, str]): + """Tests LIMS projwct dict against a LIMS project pydantic model.""" + + # GIVEN LIMS project + + # WHEN instantiating + lims_project = LimsProject.model_validate(lims_project_raw) + + # THEN assert that it was successfully created + assert isinstance(lims_project, LimsProject) From 8833035e760823ce32f0f626a6870bb0a4744318 Mon Sep 17 00:00:00 2001 From: henrikstranneheim Date: Sun, 28 Jul 2024 17:33:55 +0200 Subject: [PATCH 4/6] feat(lims) WIP --- cg/apps/lims/api.py | 111 ++++++++++++++++++--------------------- cg/models/lims/sample.py | 22 ++++++-- 2 files changed, 71 insertions(+), 62 deletions(-) diff --git a/cg/apps/lims/api.py b/cg/apps/lims/api.py index 85f7a8a38b..da94076312 100644 --- a/cg/apps/lims/api.py +++ b/cg/apps/lims/api.py @@ -2,7 +2,6 @@ import logging from datetime import date, datetime -from typing import Any from dateutil.parser import parse as parse_date from genologics.entities import Artifact, Process, Researcher, Sample @@ -18,6 +17,7 @@ ) from cg.exc import LimsDataError +from ...models.lims.sample import LimsProject, LimsSample from .order import OrderHandler SEX_MAP = {"F": "female", "M": "male", "Unknown": "unknown", "unknown": "unknown"} @@ -54,12 +54,12 @@ def __init__(self, config): def user(self) -> Researcher: return self.get_researchers(username=self.username)[0] - def sample(self, lims_id: str) -> dict[str, Any]: + def sample(self, lims_id: str) -> LimsSample: """Return sample by ID from the LIMS database.""" lims_sample = {} try: sample = Sample(self, id=lims_id) - lims_sample: dict[str, Any] = self._export_sample(sample) + lims_sample: LimsSample = self._export_sample(sample) except HTTPError as error: LOG.warning(f"Sample {lims_id} not found in LIMS: {error}") return lims_sample @@ -72,45 +72,45 @@ def get_source(self, lims_id: str) -> str | None: """Return the source from LIMS for a given sample ID. Return 'None' if no source information is set or if sample is not found or cannot be fetched from LIMS.""" - lims_sample: dict[str, Any] = self.sample(lims_id=lims_id) - return lims_sample.get("source") + lims_sample: LimsSample = self.sample(lims_id=lims_id) + return lims_sample.source @staticmethod - def _export_project(lims_project) -> dict: + def _export_project(lims_project) -> LimsProject: """Fetch relevant information from a lims project object""" - return { - "id": lims_project.id, - "name": lims_project.name, - "date": parse_date(lims_project.open_date) if lims_project.open_date else None, - } + return LimsProject( + id=lims_project.id, + name=lims_project.name, + date=parse_date(lims_project.open_date) if lims_project.open_date else None, + ) def _export_sample(self, lims_sample): """Get data from a LIMS sample.""" udfs = lims_sample.udf - return { - "id": lims_sample.id, - "name": lims_sample.name, - "project": self._export_project(lims_sample.project), - "family": udfs.get("familyID"), - "customer": udfs.get("customer"), - "sex": SEX_MAP.get(udfs.get("Gender")), - "father": udfs.get("fatherID"), - "mother": udfs.get("motherID"), - "source": udfs.get("Source"), - "status": udfs.get("Status"), - "panels": udfs.get("Gene List").split(";") if udfs.get("Gene List") else None, - "priority": udfs.get("priority"), - "received": self.get_received_date(lims_sample.id), - "application": udfs.get("Sequencing Analysis"), - "application_version": ( + return LimsSample( + id=lims_sample.id, + name=lims_sample.name, + project=self._export_project(lims_sample.project), + case=udfs.get("familyID"), + customer=udfs.get("customer"), + sex=SEX_MAP.get(udfs.get("Gender")), + father=udfs.get("fatherID"), + mother=udfs.get("motherID"), + source=udfs.get("Source"), + status=udfs.get("Status"), + panels=udfs.get("Gene List").split(";") if udfs.get("Gene List") else None, + priority=udfs.get("priority"), + received=self.get_received_date(lims_sample.id), + application=udfs.get("Sequencing Analysis"), + application_version=( int(udfs["Application Tag Version"]) if udfs.get("Application Tag Version") else None ), - "comment": udfs.get("comment"), - "concentration_ng_ul": udfs.get("Concentration (ng/ul)"), - "passed_initial_qc": udfs.get("Passed Initial QC"), - } + comment=udfs.get("comment"), + concentration_ng_ul=udfs.get("Concentration (ng/ul)"), + passed_initial_qc=udfs.get("Passed Initial QC"), + ) def get_received_date(self, lims_id: str) -> date: """Get the date when a sample was received.""" @@ -180,21 +180,23 @@ def family(self, customer: str, family: str): """Fetch information about a family of samples.""" filters = {"customer": customer, "familyID": family} lims_samples = self.get_samples(udf=filters) - samples_data = [self._export_sample(lims_sample) for lims_sample in lims_samples] + samples_data: list[LimsSample] = [ + self._export_sample(lims_sample) for lims_sample in lims_samples + ] # get family level data family_data = {"family": family, "customer": customer, "samples": []} priorities = set() panels = set() for sample_data in samples_data: - priorities.add(sample_data["priority"]) - if sample_data["panels"]: - panels.update(sample_data["panels"]) + priorities.add(sample_data.priority) + if sample_data.panels: + panels.update(sample_data.panels) family_data["samples"].append(sample_data) if len(priorities) == 1: family_data["priority"] = priorities.pop() - elif len(priorities) < 1: + elif not priorities: raise LimsDataError(f"unable to determine family priority: {priorities}") else: for prio in [ @@ -221,8 +223,7 @@ def update_sample( lims_sample = Sample(self, id=lims_id) if sex: - lims_gender = REV_SEX_MAP.get(sex) - if lims_gender: + if lims_gender := REV_SEX_MAP.get(sex): lims_sample.udf[PROP2UDF["sex"]] = lims_gender if name: lims_sample.name = name @@ -307,9 +308,7 @@ def _get_methods(self, step_names_udfs: dict[str, dict], lims_id: str) -> str | ) ) - sorted_methods = self._sort_by_date_run(methods) - - if sorted_methods: + if sorted_methods := self._sort_by_date_run(methods): method = sorted_methods[METHOD_INDEX] if ( @@ -402,18 +401,18 @@ def _find_twist_capture_kits(artifacts, udf_key): def get_sample_comment(self, sample_id: str) -> str | None: """Return the comment of the sample.""" - lims_sample: dict[str, Any] = self.sample(sample_id) + lims_sample: LimsSample = self.sample(sample_id) comment = None if lims_sample: - comment: str = lims_sample.get("comment") + comment: str | None = lims_sample.comment return comment def get_sample_project(self, sample_id: str) -> str | None: """Return the LIMS ID of the sample associated project if sample exists in LIMS.""" - lims_sample: dict[str, Any] = self.sample(sample_id) + lims_sample: LimsSample = self.sample(sample_id) project_id = None if lims_sample: - project_id: str = lims_sample.get("project").get("id") + project_id: str = lims_sample.project.id return project_id def get_sample_rin(self, sample_id: str) -> float | None: @@ -438,8 +437,8 @@ def get_sample_dv200(self, sample_id: str) -> float | None: def has_sample_passed_initial_qc(self, sample_id: str) -> bool | None: """Return the outcome of the initial QC protocol of the given sample.""" - lims_sample: dict[str, Any] = self.sample(sample_id) - initial_qc_udf: str | None = lims_sample.get("passed_initial_qc") + lims_sample: LimsSample = self.sample(sample_id) + initial_qc_udf: str | None = lims_sample.passed_initial_qc initial_qc: bool | None = eval(initial_qc_udf) if initial_qc_udf else None return initial_qc @@ -448,21 +447,17 @@ def _get_rna_input_amounts(self, sample_id: str) -> list[tuple[datetime, float]] step_names_udfs: dict[str] = MASTER_STEPS_UDFS["rna_prep_step"] input_amounts: list[tuple[datetime, float]] = [] try: - for process_type in step_names_udfs: + for process_type, udf_key in step_names_udfs.items(): artifacts: list[Artifact] = self.get_artifacts( samplelimsid=sample_id, process_type=process_type, type=LimsArtifactTypes.ANALYTE, ) - udf_key: str = step_names_udfs[process_type] - for artifact in artifacts: - input_amounts.append( - ( - artifact.parent_process.date_run, - artifact.udf.get(udf_key), - ) - ) + input_amounts.extend( + (artifact.parent_process.date_run, artifact.udf.get(udf_key)) + for artifact in artifacts + ) except HTTPError as error: LOG.warning(f"Sample {sample_id} not found in LIMS: {error}") return input_amounts @@ -472,9 +467,7 @@ def _get_last_used_input_amount( ) -> float | None: """Return the latest used input amount.""" sorted_input_amounts: list[tuple[datetime, float]] = self._sort_by_date_run(input_amounts) - if not sorted_input_amounts: - return None - return sorted_input_amounts[0][1] + return sorted_input_amounts[0][1] if sorted_input_amounts else None def get_latest_rna_input_amount(self, sample_id: str) -> float | None: """Return the input amount used in the latest preparation of an RNA sample.""" diff --git a/cg/models/lims/sample.py b/cg/models/lims/sample.py index 9de696e780..949ebda275 100644 --- a/cg/models/lims/sample.py +++ b/cg/models/lims/sample.py @@ -62,18 +62,34 @@ class Udf(BaseModel): @field_validator("sex", mode="before") @classmethod - def get_udf_sex(cls, sex: Literal["male", "female", "unknown"]) -> str: + def set_udf_sex(cls, sex: Literal["male", "female", "unknown"]) -> str: return SEX_MAP.get(sex, "unknown") class LimsSample(BaseModel): - name: str + application: str | None = None + application_version: str | None = None + case: str | None = None + comment: str | None = None + concentration_ng_ul: str | None = None container: str = "Tube" container_name: str | None = None - well_position: str | None = None + customer: str | None = None + father: str | None = None + id: str | None = None index_sequence: str | None = None + mother: str | None = None + name: str + panels: list[str] | None = None + passed_initial_qc: str | None = None + priority: str | None = None project: LimsProject | None = None + received: str | None = None + sex: str | None = None + source: str | None = None + status: str | None = None udfs: Udf | None = None + well_position: str | None = None @classmethod def parse_obj(cls, sample_raw: dict): From c2cd1c439a280e793799ee517fd059a34e294fc2 Mon Sep 17 00:00:00 2001 From: henrikstranneheim Date: Tue, 6 Aug 2024 12:12:39 +0200 Subject: [PATCH 5/6] feat(update): Linters --- .github/workflows/black.yml | 2 +- .pre-commit-config.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/black.yml b/.github/workflows/black.yml index e7f38632b2..3931f22375 100644 --- a/.github/workflows/black.yml +++ b/.github/workflows/black.yml @@ -18,4 +18,4 @@ jobs: uses: psf/black@stable with: options: ". --check --line-length 100" - version: "~=24.1.0" + version: "~=24.8.0" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bd09b0991b..1e088012b1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/psf/black - rev: 24.4.0 + rev: 24.8.0 hooks: - id: black args: [--line-length=100] @@ -10,7 +10,7 @@ repos: - id: isort name: isort - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.3.7 + rev: v0.5.6 hooks: - id: ruff From 5285a3c6dd61bffc9f5bc8ad49f570a69326b06e Mon Sep 17 00:00:00 2001 From: henrikstranneheim Date: Fri, 16 Aug 2024 16:40:36 +0200 Subject: [PATCH 6/6] fix(cmp) --- tests/meta/orders/test_meta_orders_lims.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/meta/orders/test_meta_orders_lims.py b/tests/meta/orders/test_meta_orders_lims.py index 5aa0639b36..91cc7a97ee 100644 --- a/tests/meta/orders/test_meta_orders_lims.py +++ b/tests/meta/orders/test_meta_orders_lims.py @@ -1,3 +1,5 @@ +import math + import pytest from cg.constants import Workflow @@ -68,7 +70,7 @@ def test_to_lims_rml(rml_order_to_submit): first_sample = samples[0] assert first_sample.udfs.pool == "pool-1" assert first_sample.udfs.volume == "30" - assert first_sample.udfs.concentration == 5.0 + assert math.isclose(a=first_sample.udfs.concentration, b=5.0, rel_tol=1e-09, abs_tol=1e-09) assert first_sample.udfs.index == "IDT DupSeq 10 bp Set B" assert first_sample.udfs.index_number == "1"