aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--wqflask/base/species.py83
-rw-r--r--wqflask/tests/unit/base/test_species.py116
-rw-r--r--wqflask/wqflask/api/gen_menu.py10
3 files changed, 166 insertions, 43 deletions
diff --git a/wqflask/base/species.py b/wqflask/base/species.py
index e3c29916..f303aabb 100644
--- a/wqflask/base/species.py
+++ b/wqflask/base/species.py
@@ -1,59 +1,66 @@
-import collections
-
-from flask import Flask, g
-
-
-from utility.logger import getLogger
-logger = getLogger(__name__)
+from collections import OrderedDict
+from dataclasses import dataclass
+from dataclasses import InitVar
+from typing import Optional, Dict
+from flask import g
+@dataclass
class TheSpecies:
- def __init__(self, dataset=None, species_name=None):
- if species_name != None:
- self.name = species_name
+ """Data related to species."""
+ dataset: Optional[Dict] = None
+ species_name: Optional[str] = None
+
+ def __post_init__(self):
+ if self.species_name is not None:
+ self.name = self.species_name
self.chromosomes = Chromosomes(species=self.name)
else:
- self.dataset = dataset
self.chromosomes = Chromosomes(dataset=self.dataset)
+@dataclass
class IndChromosome:
- def __init__(self, name, length):
- self.name = name
- self.length = length
+ """Data related to IndChromosome"""
+ name: str
+ length: int
@property
def mb_length(self):
- """Chromosome length in megabases"""
+ """Chromosome length in mega-bases"""
return self.length / 1000000
+@dataclass
class Chromosomes:
- def __init__(self, dataset=None, species=None):
- self.chromosomes = collections.OrderedDict()
- if species != None:
- query = """
- Select
- Chr_Length.Name, Chr_Length.OrderId, Length from Chr_Length, Species
- where
- Chr_Length.SpeciesId = Species.SpeciesId AND
- Species.Name = '%s'
- Order by OrderId
- """ % species.capitalize()
- else:
+ """Data related to a chromosome"""
+ dataset: InitVar[Dict] = None
+ species: Optional[str] = None
+
+ def __post_init__(self, dataset):
+ if self.species is None:
self.dataset = dataset
- query = """
- Select
- Chr_Length.Name, Chr_Length.OrderId, Length from Chr_Length, InbredSet
- where
- Chr_Length.SpeciesId = InbredSet.SpeciesId AND
- InbredSet.Name = '%s'
- Order by OrderId
- """ % self.dataset.group.name
- logger.sql(query)
+ @property
+ def chromosomes(self):
+ """Lazily fetch the chromosomes"""
+ chromosomes = OrderedDict()
+ if self.species is not None:
+ query = (
+ "SELECT Chr_Length.Name, Chr_Length.OrderId, Length "
+ "FROM Chr_Length, Species WHERE "
+ "Chr_Length.SpeciesId = Species.SpeciesId AND "
+ "Species.Name = "
+ "'%s' ORDER BY OrderId" % self.species.capitalize())
+ else:
+ query = (
+ "SELECT Chr_Length.Name, Chr_Length.OrderId, "
+ "Length FROM Chr_Length, InbredSet WHERE "
+ "Chr_Length.SpeciesId = InbredSet.SpeciesId AND "
+ "InbredSet.Name = "
+ "'%s' ORDER BY OrderId" % self.dataset.group.name)
results = g.db.execute(query).fetchall()
-
for item in results:
- self.chromosomes[item.OrderId] = IndChromosome(
+ chromosomes[item.OrderId] = IndChromosome(
item.Name, item.Length)
+ return chromosomes
diff --git a/wqflask/tests/unit/base/test_species.py b/wqflask/tests/unit/base/test_species.py
new file mode 100644
index 00000000..9b5c023c
--- /dev/null
+++ b/wqflask/tests/unit/base/test_species.py
@@ -0,0 +1,116 @@
+"""Tests wqflask/base/species.py"""
+
+import unittest
+from unittest import mock
+from base.species import TheSpecies
+from base.species import IndChromosome
+from base.species import Chromosomes
+from collections import OrderedDict
+from wqflask import app
+from dataclasses import dataclass
+
+
+@dataclass
+class MockChromosome:
+ OrderId: int
+ Name: str
+ Length: int
+
+
+@dataclass
+class MockGroup:
+ name: str
+
+
+@dataclass
+class MockDataset:
+ group: MockGroup
+
+
+class TestTheSpecies(unittest.TestCase):
+ """Tests for TheSpecies class"""
+ @mock.patch('base.species.Chromosomes')
+ def test_create_species_with_null_species_name(self, mock_chromosome):
+ """Test that TheSpecies is instantiated correctly when the
+species_name is provided."""
+ mock_chromosome.return_value = 1
+ test_species = TheSpecies(dataset="random_dataset", species_name="a")
+ self.assertEqual(test_species.name, "a")
+ self.assertEqual(test_species.chromosomes, 1)
+
+ @mock.patch('base.species.Chromosomes')
+ def test_create_species_with_species_name(self, mock_chromosome):
+ """Test that TheSpecies is instantiated correctly when the
+species_name is not provided."""
+ mock_chromosome.return_value = 1
+ test_species = TheSpecies(dataset="random_dataset")
+ self.assertEqual(test_species.dataset, "random_dataset")
+ self.assertEqual(test_species.chromosomes, 1)
+ mock_chromosome.assert_called_once_with(dataset="random_dataset")
+
+
+class TestIndChromosome(unittest.TestCase):
+ """Tests for IndChromosome class"""
+
+ def test_create_ind_chromosome(self):
+ """Test that IndChromosome is instantiated correctly"""
+ test_ind_chromosome = IndChromosome(name="Test", length=10000000)
+ self.assertEqual(test_ind_chromosome.name, "Test")
+ self.assertEqual(test_ind_chromosome.length, 10000000)
+ self.assertEqual(test_ind_chromosome.mb_length, 10)
+
+
+class TestChromosomes(unittest.TestCase):
+ """Tests for Chromosomes class"""
+ maxDiff = None
+
+ def setUp(self):
+ self.app_context = app.app_context()
+ self.app_context.push()
+
+ def tearDown(self):
+ self.app_context.pop()
+
+ @mock.patch("base.species.g")
+ def test_create_chromosomes_with_no_species(self, mock_db):
+ """Test instantiating a chromosome without a species"""
+ mock_db.db.execute.return_value.fetchall.return_value = [
+ MockChromosome(1, "X", 100),
+ MockChromosome(2, "Y", 1000),
+ MockChromosome(3, "Z", 10000),
+ ]
+ mock_dataset = MockDataset(MockGroup("Random"))
+ test_chromosomes = Chromosomes(dataset=mock_dataset)
+ self.assertEqual(
+ list(test_chromosomes.chromosomes.keys()),
+ [1, 2, 3]
+ )
+ self.assertEqual(test_chromosomes.dataset, mock_dataset)
+ mock_db.db.execute.assert_called_with(
+ "SELECT Chr_Length.Name, Chr_Length.OrderId, Length "
+ "FROM Chr_Length, InbredSet WHERE "
+ "Chr_Length.SpeciesId = InbredSet.SpeciesId AND "
+ "InbredSet.Name = 'Random' ORDER BY OrderId"
+ )
+
+ @mock.patch("base.species.g")
+ def test_create_chromosomes_with_species(self, mock_db):
+ """Test instantiating a chromosome with a species"""
+ mock_db.db.execute.return_value.fetchall.return_value = [
+ MockChromosome(1, "X", 100),
+ MockChromosome(2, "Y", 1000),
+ MockChromosome(3, "Z", 10000),
+ ]
+ mock_dataset = MockDataset(MockGroup("Random"))
+ test_chromosomes = Chromosomes(dataset=mock_dataset,
+ species="testSpecies")
+ self.assertEqual(
+ list(test_chromosomes.chromosomes.keys()),
+ [1, 2, 3]
+ )
+ mock_db.db.execute.assert_called_with(
+ "SELECT Chr_Length.Name, Chr_Length.OrderId, Length "
+ "FROM Chr_Length, Species WHERE "
+ "Chr_Length.SpeciesId = Species.SpeciesId AND "
+ "Species.Name = 'Testspecies' ORDER BY OrderId"
+ )
diff --git a/wqflask/wqflask/api/gen_menu.py b/wqflask/wqflask/api/gen_menu.py
index e65b36e4..7f4ec1bc 100644
--- a/wqflask/wqflask/api/gen_menu.py
+++ b/wqflask/wqflask/api/gen_menu.py
@@ -178,12 +178,12 @@ def build_datasets(species, group, type_name):
elif type_name == "Genotypes":
results = g.db.execute(
- ("SELECT InfoFiles.GN_AccesionId " +
+ ("SELECT InfoFiles.GN_AccesionId "
"FROM InfoFiles, GenoFreeze, InbredSet "
- + "WHERE InbredSet.Name = '{}' AND "
- + "GenoFreeze.InbredSetId = InbredSet.Id AND "
- + "InfoFiles.InfoPageName = GenoFreeze.ShortName "
- + "ORDER BY GenoFreeze.CreateTime DESC").format(group)).fetchone()
+ "WHERE InbredSet.Name = '{}' AND "
+ "GenoFreeze.InbredSetId = InbredSet.Id AND "
+ "InfoFiles.InfoPageName = GenoFreeze.ShortName "
+ "ORDER BY GenoFreeze.CreateTime DESC").format(group)).fetchone()
dataset_id = "None"
if bool(results):