From 95f4c1d6e1d0930393fef6f09ffbb8b5ff69dbdd Mon Sep 17 00:00:00 2001 From: Matt Stone Date: Tue, 12 Mar 2024 09:12:14 -0400 Subject: [PATCH] refactor: fix circular import --- pybedlite/bed_record.py | 31 ++++++++++++++++++++++++ pybedlite/overlap_detector.py | 20 --------------- pybedlite/tests/test_overlap_detector.py | 2 +- 3 files changed, 32 insertions(+), 21 deletions(-) diff --git a/pybedlite/bed_record.py b/pybedlite/bed_record.py index a1786ff..72ecbbb 100644 --- a/pybedlite/bed_record.py +++ b/pybedlite/bed_record.py @@ -12,12 +12,19 @@ pertaining to a BED record. """ +from __future__ import annotations + import attr import enum from typing import Optional from typing import Tuple from typing import List from typing import ClassVar +from typing import Type +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from pybedlite.overlap_detector import Interval """Maximum BED fields that can be present in a well formed BED file written to specification""" @@ -189,3 +196,27 @@ def as_bed_line(self, number_of_output_fields: Optional[int] = None) -> str: ) fields = self.bed_fields[:number_of_output_fields] return "\t".join(fields) + + @classmethod + def from_interval(cls: Type["BedRecord"], interval: Interval) -> "BedRecord": + """ + Construct a `BedRecord` from a `Interval` instance. + + **Note that `Interval` cannot represent a `BedRecord` with a missing strand.** + Converting a record with no strand to `Interval` and then back to `BedRecord` will result in + a record with **positive strand**. + + Args: + interval: The `Interval` instance to convert. + + Returns: + A `BedRecord` corresponding to the same region specified in the interval. + """ + + return BedRecord( + chrom=interval.refname, + start=interval.start, + end=interval.end, + strand=BedStrand.Negative if interval.negative else BedStrand.Positive, + name=interval.name, + ) diff --git a/pybedlite/overlap_detector.py b/pybedlite/overlap_detector.py index a35a9b5..325cef6 100644 --- a/pybedlite/overlap_detector.py +++ b/pybedlite/overlap_detector.py @@ -102,26 +102,6 @@ def length(self) -> int: """Returns the length of the interval.""" return self.end - self.start - def to_bedrecord(self) -> BedRecord: - """ - Convert an `Interval` to a `BedRecord` instance. - - **Note that `Interval` cannot represent a `BedRecord` with a missing strand.** - Converting a record with no strand to `Interval` and then back to `BedRecord` will result in - a record with **positive strand**. - - Returns: - An `Interval` corresponding to the same region specified in the record. - """ - - return BedRecord( - chrom=self.refname, - start=self.start, - end=self.end, - strand=BedStrand.Negative if self.negative else BedStrand.Positive, - name=self.name, - ) - @classmethod def from_bedrecord(cls: Type["Interval"], record: BedRecord) -> "Interval": """ diff --git a/pybedlite/tests/test_overlap_detector.py b/pybedlite/tests/test_overlap_detector.py index e23c959..e8e9fd5 100644 --- a/pybedlite/tests/test_overlap_detector.py +++ b/pybedlite/tests/test_overlap_detector.py @@ -177,7 +177,7 @@ def test_construction_from_interval(bed_records: List[BedRecord]) -> None: # I don't think pytest.mark.parametrize can accept a fixture and expand over its values. # For loop it is. for record in bed_records: - new_record = Interval.from_bedrecord(record).to_bedrecord() + new_record = BedRecord.from_interval(Interval.from_bedrecord(record)) assert new_record.chrom == record.chrom assert new_record.start == record.start