From 394f38321ee1981e5b78195ff25317a77c0f0de0 Mon Sep 17 00:00:00 2001 From: clintval Date: Fri, 8 Nov 2024 15:31:22 -0800 Subject: [PATCH] feat: unfreeze dataclasses for speed --- README.md | 2 +- bedspec/_bedspec.py | 26 +++++++++++++------------- tests/test_bedspec.py | 16 ++++++++++++++++ 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index d23fd79..c40bd27 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,7 @@ For example, to create a custom BED3+1 class: >>> >>> from bedspec import SimpleBed >>> ->>> @dataclass(eq=True, frozen=True) +>>> @dataclass(eq=True) ... class Bed3Plus1(SimpleBed): ... refname: str ... start: int diff --git a/bedspec/_bedspec.py b/bedspec/_bedspec.py index 5b99b2e..6fce3b8 100644 --- a/bedspec/_bedspec.py +++ b/bedspec/_bedspec.py @@ -89,7 +89,7 @@ def territory(self) -> Iterator[ReferenceSpan]: """A type variable for any kind of BED record type.""" -@dataclass(frozen=True) +@dataclass class PointBed(BedLike, ABC): """An abstract class for a BED record that describes a 0-based 1-length point.""" @@ -112,7 +112,7 @@ def territory(self) -> Iterator[ReferenceSpan]: yield Bed3(refname=self.refname, start=self.start, end=self.start + 1) -@dataclass(frozen=True) +@dataclass class SimpleBed(BedLike, ReferenceSpan, ABC): """An abstract class for a BED record that describes a contiguous linear interval.""" @@ -141,7 +141,7 @@ def territory(self) -> Iterator[ReferenceSpan]: yield self -@dataclass(frozen=True) +@dataclass class PairBed(BedLike, ABC): """An abstract base class for a BED record that describes a pair of linear linear intervals.""" @@ -181,7 +181,7 @@ def territory(self) -> Iterator[ReferenceSpan]: yield self.bed2 -@dataclass(eq=True, frozen=True) +@dataclass(eq=True, slots=True) class BedColor: """The color of a BED record in red, green, and blue color values.""" @@ -209,7 +209,7 @@ def __str__(self) -> str: return f"{self.r},{self.g},{self.b}" -@dataclass(eq=True, frozen=True) +@dataclass(eq=True, slots=True) class Bed2(PointBed): """A BED2 record that describes a single 0-based 1-length point.""" @@ -217,7 +217,7 @@ class Bed2(PointBed): start: int -@dataclass(eq=True, frozen=True) +@dataclass(eq=True, slots=True) class Bed3(SimpleBed): """A BED3 record that describes a contiguous linear interval.""" @@ -226,7 +226,7 @@ class Bed3(SimpleBed): end: int = field(kw_only=True) -@dataclass(eq=True, frozen=True) +@dataclass(eq=True, slots=True) class Bed4(SimpleBed): """A BED4 record that describes a contiguous linear interval.""" @@ -236,7 +236,7 @@ class Bed4(SimpleBed): name: str | None = field(kw_only=True) -@dataclass(eq=True, frozen=True) +@dataclass(eq=True, slots=True) class Bed5(SimpleBed, Named): """A BED5 record that describes a contiguous linear interval.""" @@ -247,7 +247,7 @@ class Bed5(SimpleBed, Named): score: int | None = field(kw_only=True) -@dataclass(eq=True, frozen=True) +@dataclass(eq=True, slots=True) class Bed6(SimpleBed, Named, Stranded): """A BED6 record that describes a contiguous linear interval.""" @@ -259,7 +259,7 @@ class Bed6(SimpleBed, Named, Stranded): strand: BedStrand | None = field(kw_only=True) -@dataclass(eq=True, frozen=True) +@dataclass(eq=True, slots=True) class Bed12(SimpleBed, Named, Stranded): """A BED12 record that describes a contiguous linear interval.""" @@ -278,7 +278,7 @@ class Bed12(SimpleBed, Named, Stranded): def __post_init__(self) -> None: """Validate this BED12 record.""" - super().__post_init__() + super(Bed12, self).__post_init__() if (self.thick_start is None) != (self.thick_end is None): raise ValueError("thick_start and thick_end must both be None or both be set!") if self.block_count is None: @@ -301,7 +301,7 @@ def __post_init__(self) -> None: raise ValueError("The last defined block's end must be equal to the BED end!") -@dataclass(eq=True, frozen=True) +@dataclass(eq=True, slots=True) class BedGraph(SimpleBed): """A bedGraph feature for continuous-valued data.""" @@ -311,7 +311,7 @@ class BedGraph(SimpleBed): value: float = field(kw_only=True) -@dataclass(eq=True, frozen=True) +@dataclass(eq=True, slots=True) class BedPE(PairBed, Named): """A BED record that describes a pair of BED records as per the bedtools spec.""" diff --git a/tests/test_bedspec.py b/tests/test_bedspec.py index 0fc2134..29813eb 100644 --- a/tests/test_bedspec.py +++ b/tests/test_bedspec.py @@ -248,6 +248,22 @@ def make_bed12( block_starts=block_starts, ) + with pytest.raises(ValueError, match="start must be greater than 0 and less than end!"): + Bed12( + refname="chr1", + start=2, + end=1, + name="bed12", + score=2, + strand=BedStrand.Positive, + thick_start=None, + thick_end=None, + item_rgb=BedColor(101, 2, 32), + block_count=None, + block_sizes=None, + block_starts=None, + ) + with pytest.raises( ValueError, match="thick_start and thick_end must both be None or both be set!" ):