From 7b8ffda6de6be67736074d707015ed22a55d1185 Mon Sep 17 00:00:00 2001 From: BonfaceKilz Date: Tue, 4 May 2021 22:17:56 +0300 Subject: tests: test_species: Add test cases for TestTheSpecies class --- wqflask/tests/unit/base/test_species.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 wqflask/tests/unit/base/test_species.py diff --git a/wqflask/tests/unit/base/test_species.py b/wqflask/tests/unit/base/test_species.py new file mode 100644 index 00000000..950909a1 --- /dev/null +++ b/wqflask/tests/unit/base/test_species.py @@ -0,0 +1,27 @@ +"""Tests wqflask/base/species.py""" + +import unittest +from unittest import mock +from base.species import TheSpecies + + +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") -- cgit v1.2.3 From 31d447d5d70cf18a41c6e139a152fe4cfb864bb4 Mon Sep 17 00:00:00 2001 From: BonfaceKilz Date: Tue, 4 May 2021 22:24:02 +0300 Subject: tests: test_species: Test that IndChromosome instantiates correctly --- wqflask/tests/unit/base/test_species.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/wqflask/tests/unit/base/test_species.py b/wqflask/tests/unit/base/test_species.py index 950909a1..42aa9092 100644 --- a/wqflask/tests/unit/base/test_species.py +++ b/wqflask/tests/unit/base/test_species.py @@ -3,6 +3,7 @@ import unittest from unittest import mock from base.species import TheSpecies +from base.species import IndChromosome class TestTheSpecies(unittest.TestCase): @@ -25,3 +26,14 @@ species_name is not provided.""" 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) -- cgit v1.2.3 From b2b81942c6dda717ec8e7beeac61477f0e67a387 Mon Sep 17 00:00:00 2001 From: BonfaceKilz Date: Tue, 4 May 2021 23:27:00 +0300 Subject: templates: test_species: Add tests for instantiating Chromosomes --- wqflask/tests/unit/base/test_species.py | 77 +++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/wqflask/tests/unit/base/test_species.py b/wqflask/tests/unit/base/test_species.py index 42aa9092..487bbd7f 100644 --- a/wqflask/tests/unit/base/test_species.py +++ b/wqflask/tests/unit/base/test_species.py @@ -4,6 +4,27 @@ 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): @@ -37,3 +58,59 @@ class TestIndChromosome(unittest.TestCase): 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) + 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" + ) + self.assertEqual( + list(test_chromosomes.chromosomes.keys()), + [1, 2, 3] + ) + self.assertEqual(test_chromosomes.dataset, mock_dataset) + + @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") + 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" + ) + self.assertEqual( + list(test_chromosomes.chromosomes.keys()), + [1, 2, 3] + ) -- cgit v1.2.3 From 7e6886d7f65307519b8d26ec43a04f8d674fc4b6 Mon Sep 17 00:00:00 2001 From: BonfaceKilz Date: Tue, 4 May 2021 23:27:34 +0300 Subject: base: species: Format SQL queries --- wqflask/base/species.py | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/wqflask/base/species.py b/wqflask/base/species.py index e3c29916..c3f4a9ab 100644 --- a/wqflask/base/species.py +++ b/wqflask/base/species.py @@ -32,28 +32,23 @@ 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() + 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: 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 + 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) results = g.db.execute(query).fetchall() - for item in results: self.chromosomes[item.OrderId] = IndChromosome( item.Name, item.Length) -- cgit v1.2.3 From 5e19a8a505dc7b8fa77fcc836892d1982c6ae36d Mon Sep 17 00:00:00 2001 From: BonfaceKilz Date: Tue, 4 May 2021 23:28:40 +0300 Subject: base: species: Remove unused import --- wqflask/base/species.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wqflask/base/species.py b/wqflask/base/species.py index c3f4a9ab..3ec7556d 100644 --- a/wqflask/base/species.py +++ b/wqflask/base/species.py @@ -1,6 +1,6 @@ import collections -from flask import Flask, g +from flask import g from utility.logger import getLogger -- cgit v1.2.3 From 453455b8bc6557c35ad279a208235f0b44aa251e Mon Sep 17 00:00:00 2001 From: BonfaceKilz Date: Tue, 4 May 2021 23:34:32 +0300 Subject: base: species: Rewrite TheSpecies class using a dataclass --- wqflask/base/species.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/wqflask/base/species.py b/wqflask/base/species.py index 3ec7556d..3865f450 100644 --- a/wqflask/base/species.py +++ b/wqflask/base/species.py @@ -1,5 +1,7 @@ import collections +from dataclasses import dataclass +from typing import Optional, Dict from flask import g @@ -7,13 +9,18 @@ from utility.logger import getLogger logger = getLogger(__name__) +@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.dataset = self.dataset self.chromosomes = Chromosomes(dataset=self.dataset) -- cgit v1.2.3 From 151cbec41a9466f8f716f24ae85c7a5b09919e01 Mon Sep 17 00:00:00 2001 From: BonfaceKilz Date: Tue, 4 May 2021 23:35:38 +0300 Subject: base: trait: Remove logging information The log adds unnecessary noise in addition to creating unwanted side-effects. --- wqflask/base/species.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/wqflask/base/species.py b/wqflask/base/species.py index 3865f450..ce646538 100644 --- a/wqflask/base/species.py +++ b/wqflask/base/species.py @@ -5,10 +5,6 @@ from typing import Optional, Dict from flask import g -from utility.logger import getLogger -logger = getLogger(__name__) - - @dataclass class TheSpecies: """Data related to species.""" @@ -54,7 +50,6 @@ class Chromosomes: "Chr_Length.SpeciesId = InbredSet.SpeciesId AND " "InbredSet.Name = " "'%s' ORDER BY OrderId" % self.dataset.group.name) - logger.sql(query) results = g.db.execute(query).fetchall() for item in results: self.chromosomes[item.OrderId] = IndChromosome( -- cgit v1.2.3 From 7c6a60d62389fa945f5a7264cde31cf00ddf9fc4 Mon Sep 17 00:00:00 2001 From: BonfaceKilz Date: Tue, 4 May 2021 23:46:00 +0300 Subject: base: species: Rewrite IndChromosome using a dataclass --- wqflask/base/species.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/wqflask/base/species.py b/wqflask/base/species.py index ce646538..628bcc56 100644 --- a/wqflask/base/species.py +++ b/wqflask/base/species.py @@ -20,14 +20,15 @@ class TheSpecies: 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 -- cgit v1.2.3 From f2c3528cc81d228a62dfd9e362d0a1202412b098 Mon Sep 17 00:00:00 2001 From: BonfaceKilz Date: Tue, 4 May 2021 23:46:45 +0300 Subject: base: species: Rewrite Chromosomes using a dataclass --- wqflask/base/species.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/wqflask/base/species.py b/wqflask/base/species.py index 628bcc56..db1975d4 100644 --- a/wqflask/base/species.py +++ b/wqflask/base/species.py @@ -1,6 +1,6 @@ -import collections - +from collections import OrderedDict from dataclasses import dataclass +from dataclasses import InitVar from typing import Optional, Dict from flask import g @@ -32,17 +32,21 @@ class IndChromosome: return self.length / 1000000 +@dataclass class Chromosomes: - def __init__(self, dataset=None, species=None): - self.chromosomes = collections.OrderedDict() - if species != None: + """Data related to a chromosome""" + dataset: InitVar[Dict] = None + species: Optional[str] = None + + def __post_init__(self, dataset): + self.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" % species.capitalize() - ) + "'%s' ORDER BY OrderId" % self.species.capitalize()) else: self.dataset = dataset query = ( -- cgit v1.2.3 From 941680d5266159fc5c9f2a65131bf283bd1cef1d Mon Sep 17 00:00:00 2001 From: BonfaceKilz Date: Tue, 4 May 2021 23:55:58 +0300 Subject: base: chromosomes: Fetch the chromosomes lazily --- wqflask/base/species.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/wqflask/base/species.py b/wqflask/base/species.py index db1975d4..430bb675 100644 --- a/wqflask/base/species.py +++ b/wqflask/base/species.py @@ -39,7 +39,13 @@ class Chromosomes: species: Optional[str] = None def __post_init__(self, dataset): - self.chromosomes = OrderedDict() + if self.species is None: + self.dataset = dataset + + @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 " @@ -48,7 +54,6 @@ class Chromosomes: "Species.Name = " "'%s' ORDER BY OrderId" % self.species.capitalize()) else: - self.dataset = dataset query = ( "SELECT Chr_Length.Name, Chr_Length.OrderId, " "Length FROM Chr_Length, InbredSet WHERE " @@ -57,5 +62,6 @@ class Chromosomes: "'%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 -- cgit v1.2.3 From 3f0d45848280b77a35a569682e93291204769cc8 Mon Sep 17 00:00:00 2001 From: BonfaceKilz Date: Tue, 4 May 2021 23:56:32 +0300 Subject: tests: test_species: Update failing tests --- wqflask/tests/unit/base/test_species.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/wqflask/tests/unit/base/test_species.py b/wqflask/tests/unit/base/test_species.py index 487bbd7f..9b5c023c 100644 --- a/wqflask/tests/unit/base/test_species.py +++ b/wqflask/tests/unit/base/test_species.py @@ -81,17 +81,17 @@ class TestChromosomes(unittest.TestCase): ] 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" ) - self.assertEqual( - list(test_chromosomes.chromosomes.keys()), - [1, 2, 3] - ) - self.assertEqual(test_chromosomes.dataset, mock_dataset) @mock.patch("base.species.g") def test_create_chromosomes_with_species(self, mock_db): @@ -104,13 +104,13 @@ class TestChromosomes(unittest.TestCase): 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" ) - self.assertEqual( - list(test_chromosomes.chromosomes.keys()), - [1, 2, 3] - ) -- cgit v1.2.3 From 2c3977eb936562c0c985ae93e4c7d16b52ee189a Mon Sep 17 00:00:00 2001 From: BonfaceKilz Date: Tue, 4 May 2021 23:57:40 +0300 Subject: api: gen_menu: Remove "+" when concatenating strings inside brackets --- wqflask/wqflask/api/gen_menu.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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): -- cgit v1.2.3 From dad8ae99812555fbb3d7e680f146c98de3322a57 Mon Sep 17 00:00:00 2001 From: BonfaceKilz Date: Wed, 5 May 2021 12:32:53 +0300 Subject: base: species: Remove redundant assignment --- wqflask/base/species.py | 1 - 1 file changed, 1 deletion(-) diff --git a/wqflask/base/species.py b/wqflask/base/species.py index 430bb675..f303aabb 100644 --- a/wqflask/base/species.py +++ b/wqflask/base/species.py @@ -16,7 +16,6 @@ class TheSpecies: self.name = self.species_name self.chromosomes = Chromosomes(species=self.name) else: - self.dataset = self.dataset self.chromosomes = Chromosomes(dataset=self.dataset) -- cgit v1.2.3