aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gn3/api/search.py27
-rw-r--r--tests/unit/test_search.py11
2 files changed, 26 insertions, 12 deletions
diff --git a/gn3/api/search.py b/gn3/api/search.py
index 0d3f9ba..e497743 100644
--- a/gn3/api/search.py
+++ b/gn3/api/search.py
@@ -135,6 +135,19 @@ def apply_si_suffix(location: str) -> int:
return int(location)
+def parse_position(spec: str) -> tuple[Maybe[int], Maybe[int]]:
+ """Parse position specifiation converting point locations to ranges."""
+ # Range
+ if ".." in spec:
+ return tuple(limit.map(apply_si_suffix) # type: ignore
+ for limit in parse_range(spec))
+ # If point location, assume +/- 50 kbases on either side.
+ else:
+ width = 50*10**3
+ point = apply_si_suffix(spec)
+ return Just(max(0, point - width)), Just(point + width)
+
+
def parse_location_field(species_query: xapian.Query,
chromosome_prefix: str, location_slot: int,
liftover_function: IntervalLiftoverFunction,
@@ -146,19 +159,11 @@ def parse_location_field(species_query: xapian.Query,
"""
def split_query(query: str) -> ChromosomalInterval:
"""Split query into chromosome and location tuple."""
- chromosome, location_str = query.lower().split(":")
+ chromosome, position_spec = query.lower().split(":")
if not chromosome.startswith("chr"):
raise ValueError
- location: tuple[Maybe[int], Maybe[int]]
- if ".." in location_str:
- location = tuple(limit.map(apply_si_suffix) # type: ignore
- for limit in parse_range(location_str))
- # If point location, assume +/- 50 kbases on either side.
- else:
- width = 50*10**3
- point = apply_si_suffix(location_str)
- location = Just(max(0, point - width)), Just(point + width)
- return ChromosomalInterval(chromosome.removeprefix("chr"), *location)
+ return ChromosomalInterval(chromosome.removeprefix("chr"),
+ *parse_position(position_spec))
def make_query(interval: ChromosomalInterval) -> xapian.Query:
# TODO: Convert the xapian index to use bases instead of megabases.
diff --git a/tests/unit/test_search.py b/tests/unit/test_search.py
index ec89a61..c535c60 100644
--- a/tests/unit/test_search.py
+++ b/tests/unit/test_search.py
@@ -3,7 +3,7 @@ from hypothesis import given, strategies as st
from pymonad.maybe import Just, Nothing
import pytest
-from gn3.api.search import apply_si_suffix, parse_range
+from gn3.api.search import apply_si_suffix, parse_range, parse_position
@pytest.mark.unit_test
@given(st.decimals(places=3, allow_nan=False, allow_infinity=False),
@@ -74,3 +74,12 @@ def test_parse_range_right_open_interval():
and no value (Nothing) for the ending of the range
"""
assert parse_range("foo..") == (Just("foo"), Nothing)
+
+@pytest.mark.unit_test
+def test_parse_position_close_to_zero_location():
+ """
+ GIVEN: A point location close to zero
+ WHEN: we parse the range
+ THEN: set the lower limit to zero, not a negative number
+ """
+ assert parse_position("25K")[0] == Just(0)