Commit a2010f1e authored by Christophe Benz's avatar Christophe Benz
Browse files

Stop using pydantic for dimension domain models

parent 999c0dae
Pipeline #339599 passed with stage
in 1 minute and 10 seconds
"""Dimension model."""
import dataclasses
from dataclasses import asdict, dataclass
from operator import attrgetter
from typing import List, Optional
from pydantic import BaseModel
from dbnomics_data_model.errors import DBnomicsDataModelError
from dbnomics_data_model.errors import DBnomicsDataModelError, DBnomicsMergeError
from dbnomics_data_model.utils import find
from .common import DimensionCode, DimensionValueCode
......@@ -27,41 +27,57 @@ class DimensionValueError(DBnomicsDataModelError):
"""Error about a dimension value."""
class DimensionValue(BaseModel):
@dataclass
class DimensionValue:
"""Dimension value definition."""
code: DimensionValueCode
label: Optional[str] = None
def merge(self, other: "DimensionValue") -> "DimensionValue":
"""Return a copy of self merged with `other`."""
assert self.code == other.code, (self, other)
return self.copy(update=dict(other))
def merge(self, other: "DimensionValue", *, force: bool = False) -> "DimensionValue":
"""Return a copy of self merged with `other`.
Raise DBnomicsMergeError if the other instance doesn't have the same code, except if `force` is `True`.
"""
if self.code != other.code and not force:
raise DBnomicsMergeError(f"{other=} does not have the same code than {self=}")
return dataclasses.replace(self, **asdict(other))
class Dimension(BaseModel):
@dataclass
class Dimension:
"""Dimension definition."""
code: DimensionCode
label: Optional[str] = None
values: List[DimensionValue]
label: Optional[str] = None
def find_value_by_code(self, dimension_value_code: DimensionValueCode) -> Optional[DimensionValue]:
"""Find a dimension value definition by its code."""
return find(lambda value: value.code == dimension_value_code, self.values, default=None)
def merge(self, other: "Dimension") -> "Dimension":
"""Return a copy of self merged with `other`."""
assert self.code == other.code, (self, other)
return self.copy(
update={
**dict(other),
"values": list(
iter_merged_items(
self.values,
other.values,
key=attrgetter("code"),
def merge(self, other: "Dimension", *, force: bool = False) -> "Dimension":
"""Return a copy of self merged with `other`.
Raise DBnomicsMergeError if the other instance doesn't have the same code, except if `force` is `True`.
"""
if self.code != other.code and not force:
raise DBnomicsMergeError(f"{other=} does not have the same code than {self=}")
return dataclasses.replace(
self,
**(
asdict(other)
| {
"values": list(
iter_merged_items(
self.values,
other.values,
key=attrgetter("code"),
)
)
),
}
}
),
)
import pytest
from dbnomics_data_model.model import Dimension, DimensionValue
def test_build_dimension_without_arguments_fails():
with pytest.raises(TypeError):
Dimension()
def test_build_dimension_with_missing_required_kwargs_fails():
with pytest.raises(TypeError):
Dimension(code="D1")
def test_build_dimension_with_required_kwargs():
dimension = Dimension(code="D1", values=[])
assert dimension.code == "D1"
assert dimension.values == []
def test_build_dimension_with_label():
dimension = Dimension(code="D1", values=[], label="D.1.")
assert dimension.code == "D1"
assert dimension.values == []
assert dimension.label == "D.1."
def test_build_dimension_with_one_value():
dimension = Dimension(code="D1", values=[DimensionValue(code="DV1")])
assert dimension.code == "D1"
assert dimension.values == [DimensionValue(code="DV1")]
def test_build_dimension_value_without_arguments_fails():
with pytest.raises(TypeError):
DimensionValue()
def test_build_dimension_value_with_required_kwargs():
dimension_value = DimensionValue(code="DV1")
assert dimension_value.code == "DV1"
def test_build_dimension_value_with_label():
dimension_value = DimensionValue(code="DV1", label="D.V.1.")
assert dimension_value.code == "DV1"
assert dimension_value.label == "D.V.1."
def test_merge_dimensions():
dimension = Dimension(
code="D1",
label="D.1.",
values=[DimensionValue(code="DV0", label="D.V.0."), DimensionValue(code="DV1", label="D.V.1.")],
)
other_dimension = Dimension(
code="D1",
label="D-1",
values=[DimensionValue(code="DV1", label="D-V-1"), DimensionValue(code="DV2", label="D-V-2")],
)
merged = dimension.merge(other_dimension)
assert merged.code == "D1"
assert merged.label == "D-1"
assert merged.values == [
DimensionValue(code="DV0", label="D.V.0."),
DimensionValue(code="DV1", label="D-V-1"),
DimensionValue(code="DV2", label="D-V-2"),
]
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment