forked from enviPath/enviPy
[Chore] Linted Files (#150)
Co-authored-by: Tim Lorsbach <tim@lorsba.ch> Reviewed-on: enviPath/enviPy#150
This commit is contained in:
@ -13,91 +13,80 @@ class CompoundTest(TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(CompoundTest, cls).setUpClass()
|
||||
cls.user = User.objects.get(username='anonymous')
|
||||
cls.package = PackageManager.create_package(cls.user, 'Anon Test Package', 'No Desc')
|
||||
cls.user = User.objects.get(username="anonymous")
|
||||
cls.package = PackageManager.create_package(cls.user, "Anon Test Package", "No Desc")
|
||||
|
||||
def test_smoke(self):
|
||||
c = Compound.create(
|
||||
self.package,
|
||||
smiles='C1C(=NOC1(C2=CC(=CC(=C2)Cl)C(F)(F)F)C(F)(F)F)C3=CC=C(C4=CC=CC=C43)C(=O)NCC(=O)NCC(F)(F)F',
|
||||
name='Afoxolaner',
|
||||
description='No Desc'
|
||||
smiles="C1C(=NOC1(C2=CC(=CC(=C2)Cl)C(F)(F)F)C(F)(F)F)C3=CC=C(C4=CC=CC=C43)C(=O)NCC(=O)NCC(F)(F)F",
|
||||
name="Afoxolaner",
|
||||
description="No Desc",
|
||||
)
|
||||
|
||||
self.assertEqual(c.default_structure.smiles,
|
||||
'C1C(=NOC1(C2=CC(=CC(=C2)Cl)C(F)(F)F)C(F)(F)F)C3=CC=C(C4=CC=CC=C43)C(=O)NCC(=O)NCC(F)(F)F')
|
||||
self.assertEqual(c.name, 'Afoxolaner')
|
||||
self.assertEqual(c.description, 'No Desc')
|
||||
self.assertEqual(
|
||||
c.default_structure.smiles,
|
||||
"C1C(=NOC1(C2=CC(=CC(=C2)Cl)C(F)(F)F)C(F)(F)F)C3=CC=C(C4=CC=CC=C43)C(=O)NCC(=O)NCC(F)(F)F",
|
||||
)
|
||||
self.assertEqual(c.name, "Afoxolaner")
|
||||
self.assertEqual(c.description, "No Desc")
|
||||
|
||||
def test_missing_smiles(self):
|
||||
with self.assertRaises(ValueError):
|
||||
_ = Compound.create(
|
||||
self.package,
|
||||
smiles=None,
|
||||
name='Afoxolaner',
|
||||
description='No Desc'
|
||||
)
|
||||
_ = Compound.create(self.package, smiles=None, name="Afoxolaner", description="No Desc")
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
_ = Compound.create(
|
||||
self.package,
|
||||
smiles='',
|
||||
name='Afoxolaner',
|
||||
description='No Desc'
|
||||
)
|
||||
_ = Compound.create(self.package, smiles="", name="Afoxolaner", description="No Desc")
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
_ = Compound.create(
|
||||
self.package,
|
||||
smiles=' ',
|
||||
name='Afoxolaner',
|
||||
description='No Desc'
|
||||
)
|
||||
_ = Compound.create(self.package, smiles=" ", name="Afoxolaner", description="No Desc")
|
||||
|
||||
def test_smiles_are_trimmed(self):
|
||||
c = Compound.create(
|
||||
self.package,
|
||||
smiles=' C1C(=NOC1(C2=CC(=CC(=C2)Cl)C(F)(F)F)C(F)(F)F)C3=CC=C(C4=CC=CC=C43)C(=O)NCC(=O)NCC(F)(F)F ',
|
||||
name='Afoxolaner',
|
||||
description='No Desc'
|
||||
smiles=" C1C(=NOC1(C2=CC(=CC(=C2)Cl)C(F)(F)F)C(F)(F)F)C3=CC=C(C4=CC=CC=C43)C(=O)NCC(=O)NCC(F)(F)F ",
|
||||
name="Afoxolaner",
|
||||
description="No Desc",
|
||||
)
|
||||
|
||||
self.assertEqual(c.default_structure.smiles,
|
||||
'C1C(=NOC1(C2=CC(=CC(=C2)Cl)C(F)(F)F)C(F)(F)F)C3=CC=C(C4=CC=CC=C43)C(=O)NCC(=O)NCC(F)(F)F')
|
||||
self.assertEqual(
|
||||
c.default_structure.smiles,
|
||||
"C1C(=NOC1(C2=CC(=CC(=C2)Cl)C(F)(F)F)C(F)(F)F)C3=CC=C(C4=CC=CC=C43)C(=O)NCC(=O)NCC(F)(F)F",
|
||||
)
|
||||
|
||||
def test_name_and_description_optional(self):
|
||||
c = Compound.create(
|
||||
self.package,
|
||||
smiles='C1C(=NOC1(C2=CC(=CC(=C2)Cl)C(F)(F)F)C(F)(F)F)C3=CC=C(C4=CC=CC=C43)C(=O)NCC(=O)NCC(F)(F)F',
|
||||
smiles="C1C(=NOC1(C2=CC(=CC(=C2)Cl)C(F)(F)F)C(F)(F)F)C3=CC=C(C4=CC=CC=C43)C(=O)NCC(=O)NCC(F)(F)F",
|
||||
)
|
||||
|
||||
self.assertEqual(c.name, 'Compound 1')
|
||||
self.assertEqual(c.description, 'no description')
|
||||
self.assertEqual(c.name, "Compound 1")
|
||||
self.assertEqual(c.description, "no description")
|
||||
|
||||
def test_empty_name_and_description_are_ignored(self):
|
||||
c = Compound.create(
|
||||
self.package,
|
||||
smiles='C1C(=NOC1(C2=CC(=CC(=C2)Cl)C(F)(F)F)C(F)(F)F)C3=CC=C(C4=CC=CC=C43)C(=O)NCC(=O)NCC(F)(F)F',
|
||||
name='',
|
||||
description='',
|
||||
smiles="C1C(=NOC1(C2=CC(=CC(=C2)Cl)C(F)(F)F)C(F)(F)F)C3=CC=C(C4=CC=CC=C43)C(=O)NCC(=O)NCC(F)(F)F",
|
||||
name="",
|
||||
description="",
|
||||
)
|
||||
|
||||
self.assertEqual(c.name, 'Compound 1')
|
||||
self.assertEqual(c.description, 'no description')
|
||||
self.assertEqual(c.name, "Compound 1")
|
||||
self.assertEqual(c.description, "no description")
|
||||
|
||||
def test_deduplication(self):
|
||||
c1 = Compound.create(
|
||||
self.package,
|
||||
smiles='C1C(=NOC1(C2=CC(=CC(=C2)Cl)C(F)(F)F)C(F)(F)F)C3=CC=C(C4=CC=CC=C43)C(=O)NCC(=O)NCC(F)(F)F',
|
||||
name='Afoxolaner',
|
||||
description='No Desc'
|
||||
smiles="C1C(=NOC1(C2=CC(=CC(=C2)Cl)C(F)(F)F)C(F)(F)F)C3=CC=C(C4=CC=CC=C43)C(=O)NCC(=O)NCC(F)(F)F",
|
||||
name="Afoxolaner",
|
||||
description="No Desc",
|
||||
)
|
||||
|
||||
c2 = Compound.create(
|
||||
self.package,
|
||||
smiles='C1C(=NOC1(C2=CC(=CC(=C2)Cl)C(F)(F)F)C(F)(F)F)C3=CC=C(C4=CC=CC=C43)C(=O)NCC(=O)NCC(F)(F)F',
|
||||
name='Afoxolaner',
|
||||
description='No Desc'
|
||||
smiles="C1C(=NOC1(C2=CC(=CC(=C2)Cl)C(F)(F)F)C(F)(F)F)C3=CC=C(C4=CC=CC=C43)C(=O)NCC(=O)NCC(F)(F)F",
|
||||
name="Afoxolaner",
|
||||
description="No Desc",
|
||||
)
|
||||
|
||||
# Check if create detects that this Compound already exist
|
||||
@ -109,36 +98,36 @@ class CompoundTest(TestCase):
|
||||
with self.assertRaises(ValueError):
|
||||
_ = Compound.create(
|
||||
self.package,
|
||||
smiles='C1C(=NOC1(C2=CC(=CC(=C2)Cl)C(F)(F)F)C(F)(F)F)C3=CC=C(C=CC=CC=C43)C(=O)NCC(=O)NCC(F)(F)F',
|
||||
name='Afoxolaner',
|
||||
description='No Desc'
|
||||
smiles="C1C(=NOC1(C2=CC(=CC(=C2)Cl)C(F)(F)F)C(F)(F)F)C3=CC=C(C=CC=CC=C43)C(=O)NCC(=O)NCC(F)(F)F",
|
||||
name="Afoxolaner",
|
||||
description="No Desc",
|
||||
)
|
||||
|
||||
def test_create_with_standardized_smiles(self):
|
||||
c = Compound.create(
|
||||
self.package,
|
||||
smiles='O=C(O)C1=CC=C([N+](=O)[O-])C=C1',
|
||||
name='Standardized SMILES',
|
||||
description='No Desc'
|
||||
smiles="O=C(O)C1=CC=C([N+](=O)[O-])C=C1",
|
||||
name="Standardized SMILES",
|
||||
description="No Desc",
|
||||
)
|
||||
self.assertEqual(len(c.structures.all()), 1)
|
||||
|
||||
cs = c.structures.all()[0]
|
||||
self.assertEqual(cs.normalized_structure, True)
|
||||
self.assertEqual(cs.smiles, 'O=C(O)C1=CC=C([N+](=O)[O-])C=C1')
|
||||
self.assertEqual(cs.smiles, "O=C(O)C1=CC=C([N+](=O)[O-])C=C1")
|
||||
|
||||
def test_create_with_non_standardized_smiles(self):
|
||||
c = Compound.create(
|
||||
self.package,
|
||||
smiles='[O-][N+](=O)c1ccc(C(=O)[O-])cc1',
|
||||
name='Non Standardized SMILES',
|
||||
description='No Desc'
|
||||
smiles="[O-][N+](=O)c1ccc(C(=O)[O-])cc1",
|
||||
name="Non Standardized SMILES",
|
||||
description="No Desc",
|
||||
)
|
||||
|
||||
self.assertEqual(len(c.structures.all()), 2)
|
||||
for cs in c.structures.all():
|
||||
if cs.normalized_structure:
|
||||
self.assertEqual(cs.smiles, 'O=C(O)C1=CC=C([N+](=O)[O-])C=C1')
|
||||
self.assertEqual(cs.smiles, "O=C(O)C1=CC=C([N+](=O)[O-])C=C1")
|
||||
break
|
||||
else:
|
||||
# Loop finished without break, lets fail...
|
||||
@ -147,51 +136,54 @@ class CompoundTest(TestCase):
|
||||
def test_add_structure_smoke(self):
|
||||
c = Compound.create(
|
||||
self.package,
|
||||
smiles='O=C(O)C1=CC=C([N+](=O)[O-])C=C1',
|
||||
name='Standardized SMILES',
|
||||
description='No Desc'
|
||||
smiles="O=C(O)C1=CC=C([N+](=O)[O-])C=C1",
|
||||
name="Standardized SMILES",
|
||||
description="No Desc",
|
||||
)
|
||||
|
||||
c.add_structure('[O-][N+](=O)c1ccc(C(=O)[O-])cc1', 'Non Standardized SMILES')
|
||||
c.add_structure("[O-][N+](=O)c1ccc(C(=O)[O-])cc1", "Non Standardized SMILES")
|
||||
|
||||
self.assertEqual(len(c.structures.all()), 2)
|
||||
|
||||
def test_add_structure_with_different_normalized_smiles(self):
|
||||
c = Compound.create(
|
||||
self.package,
|
||||
smiles='O=C(O)C1=CC=C([N+](=O)[O-])C=C1',
|
||||
name='Standardized SMILES',
|
||||
description='No Desc'
|
||||
smiles="O=C(O)C1=CC=C([N+](=O)[O-])C=C1",
|
||||
name="Standardized SMILES",
|
||||
description="No Desc",
|
||||
)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
c.add_structure(
|
||||
'C1C(=NOC1(C2=CC(=CC(=C2)Cl)C(F)(F)F)C(F)(F)F)C3=CC=C(C4=CC=CC=C43)C(=O)NCC(=O)NCC(F)(F)F',
|
||||
'Different Standardized SMILES')
|
||||
"C1C(=NOC1(C2=CC(=CC(=C2)Cl)C(F)(F)F)C(F)(F)F)C3=CC=C(C4=CC=CC=C43)C(=O)NCC(=O)NCC(F)(F)F",
|
||||
"Different Standardized SMILES",
|
||||
)
|
||||
|
||||
def test_delete(self):
|
||||
c = Compound.create(
|
||||
self.package,
|
||||
smiles='O=C(O)C1=CC=C([N+](=O)[O-])C=C1',
|
||||
name='Standardization Test',
|
||||
description='No Desc'
|
||||
smiles="O=C(O)C1=CC=C([N+](=O)[O-])C=C1",
|
||||
name="Standardization Test",
|
||||
description="No Desc",
|
||||
)
|
||||
|
||||
c.delete()
|
||||
|
||||
self.assertEqual(Compound.objects.filter(package=self.package).count(), 0)
|
||||
self.assertEqual(CompoundStructure.objects.filter(compound__package=self.package).count(), 0)
|
||||
self.assertEqual(
|
||||
CompoundStructure.objects.filter(compound__package=self.package).count(), 0
|
||||
)
|
||||
|
||||
def test_set_as_default_structure(self):
|
||||
c1 = Compound.create(
|
||||
self.package,
|
||||
smiles='O=C(O)C1=CC=C([N+](=O)[O-])C=C1',
|
||||
name='Standardized SMILES',
|
||||
description='No Desc'
|
||||
smiles="O=C(O)C1=CC=C([N+](=O)[O-])C=C1",
|
||||
name="Standardized SMILES",
|
||||
description="No Desc",
|
||||
)
|
||||
default_structure = c1.default_structure
|
||||
|
||||
c2 = c1.add_structure('[O-][N+](=O)c1ccc(C(=O)[O-])cc1', 'Non Standardized SMILES')
|
||||
c2 = c1.add_structure("[O-][N+](=O)c1ccc(C(=O)[O-])cc1", "Non Standardized SMILES")
|
||||
|
||||
c1.set_default_structure(c2)
|
||||
self.assertNotEqual(default_structure, c2)
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
from epdb.logic import PackageManager
|
||||
from epdb.models import Compound, User, Reaction
|
||||
@ -12,50 +11,47 @@ class CopyTest(TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(CopyTest, cls).setUpClass()
|
||||
cls.user = User.objects.get(username='anonymous')
|
||||
cls.package = PackageManager.create_package(cls.user, 'Source Package', 'No Desc')
|
||||
cls.user = User.objects.get(username="anonymous")
|
||||
cls.package = PackageManager.create_package(cls.user, "Source Package", "No Desc")
|
||||
cls.AFOXOLANER = Compound.create(
|
||||
cls.package,
|
||||
smiles='C1C(=NOC1(C2=CC(=CC(=C2)Cl)C(F)(F)F)C(F)(F)F)C3=CC=C(C4=CC=CC=C43)C(=O)NCC(=O)NCC(F)(F)F',
|
||||
name='Afoxolaner',
|
||||
description='Test compound for copying'
|
||||
smiles="C1C(=NOC1(C2=CC(=CC(=C2)Cl)C(F)(F)F)C(F)(F)F)C3=CC=C(C4=CC=CC=C43)C(=O)NCC(=O)NCC(F)(F)F",
|
||||
name="Afoxolaner",
|
||||
description="Test compound for copying",
|
||||
)
|
||||
|
||||
cls.FOUR_NITROBENZOIC_ACID = Compound.create(
|
||||
cls.package,
|
||||
smiles='[O-][N+](=O)c1ccc(C(=O)[O-])cc1', # Normalized: O=C(O)C1=CC=C([N+](=O)[O-])C=C1',
|
||||
name='Test Compound',
|
||||
description='Compound with multiple structures'
|
||||
smiles="[O-][N+](=O)c1ccc(C(=O)[O-])cc1", # Normalized: O=C(O)C1=CC=C([N+](=O)[O-])C=C1',
|
||||
name="Test Compound",
|
||||
description="Compound with multiple structures",
|
||||
)
|
||||
|
||||
cls.ETHANOL = Compound.create(
|
||||
cls.package,
|
||||
smiles='CCO',
|
||||
name='Ethanol',
|
||||
description='Simple alcohol'
|
||||
cls.package, smiles="CCO", name="Ethanol", description="Simple alcohol"
|
||||
)
|
||||
cls.target_package = PackageManager.create_package(cls.user, 'Target Package', 'No Desc')
|
||||
cls.target_package = PackageManager.create_package(cls.user, "Target Package", "No Desc")
|
||||
|
||||
cls.reaction_educt = Compound.create(
|
||||
cls.package,
|
||||
smiles='C(CCl)Cl',
|
||||
name='1,2-Dichloroethane',
|
||||
description='Eawag BBD compound c0001'
|
||||
smiles="C(CCl)Cl",
|
||||
name="1,2-Dichloroethane",
|
||||
description="Eawag BBD compound c0001",
|
||||
).default_structure
|
||||
|
||||
cls.reaction_product = Compound.create(
|
||||
cls.package,
|
||||
smiles='C(CO)Cl',
|
||||
name='2-Chloroethanol',
|
||||
description='Eawag BBD compound c0005'
|
||||
smiles="C(CO)Cl",
|
||||
name="2-Chloroethanol",
|
||||
description="Eawag BBD compound c0005",
|
||||
).default_structure
|
||||
|
||||
cls.REACTION = Reaction.create(
|
||||
package=cls.package,
|
||||
name='Eawag BBD reaction r0001',
|
||||
name="Eawag BBD reaction r0001",
|
||||
educts=[cls.reaction_educt],
|
||||
products=[cls.reaction_product],
|
||||
multi_step=False
|
||||
multi_step=False,
|
||||
)
|
||||
|
||||
def test_compound_copy_basic(self):
|
||||
@ -68,7 +64,9 @@ class CopyTest(TestCase):
|
||||
self.assertEqual(self.AFOXOLANER.description, copied_compound.description)
|
||||
self.assertEqual(copied_compound.package, self.target_package)
|
||||
self.assertEqual(self.AFOXOLANER.package, self.package)
|
||||
self.assertEqual(self.AFOXOLANER.default_structure.smiles, copied_compound.default_structure.smiles)
|
||||
self.assertEqual(
|
||||
self.AFOXOLANER.default_structure.smiles, copied_compound.default_structure.smiles
|
||||
)
|
||||
|
||||
def test_compound_copy_with_multiple_structures(self):
|
||||
"""Test copying a compound with multiple structures"""
|
||||
@ -86,7 +84,7 @@ class CopyTest(TestCase):
|
||||
self.assertIsNotNone(copied_compound.default_structure)
|
||||
self.assertEqual(
|
||||
copied_compound.default_structure.smiles,
|
||||
self.FOUR_NITROBENZOIC_ACID.default_structure.smiles
|
||||
self.FOUR_NITROBENZOIC_ACID.default_structure.smiles,
|
||||
)
|
||||
|
||||
def test_compound_copy_preserves_aliases(self):
|
||||
@ -95,15 +93,15 @@ class CopyTest(TestCase):
|
||||
original_compound = self.ETHANOL
|
||||
|
||||
# Add aliases if the method exists
|
||||
if hasattr(original_compound, 'add_alias'):
|
||||
original_compound.add_alias('Ethyl alcohol')
|
||||
original_compound.add_alias('Grain alcohol')
|
||||
if hasattr(original_compound, "add_alias"):
|
||||
original_compound.add_alias("Ethyl alcohol")
|
||||
original_compound.add_alias("Grain alcohol")
|
||||
|
||||
mapping = dict()
|
||||
copied_compound = original_compound.copy(self.target_package, mapping)
|
||||
|
||||
# Verify aliases were copied if they exist
|
||||
if hasattr(original_compound, 'aliases') and hasattr(copied_compound, 'aliases'):
|
||||
if hasattr(original_compound, "aliases") and hasattr(copied_compound, "aliases"):
|
||||
original_aliases = original_compound.aliases
|
||||
copied_aliases = copied_compound.aliases
|
||||
self.assertEqual(original_aliases, copied_aliases)
|
||||
@ -113,10 +111,10 @@ class CopyTest(TestCase):
|
||||
original_compound = self.ETHANOL
|
||||
|
||||
# Add external identifiers if the methods exist
|
||||
if hasattr(original_compound, 'add_cas_number'):
|
||||
original_compound.add_cas_number('64-17-5')
|
||||
if hasattr(original_compound, 'add_pubchem_compound_id'):
|
||||
original_compound.add_pubchem_compound_id('702')
|
||||
if hasattr(original_compound, "add_cas_number"):
|
||||
original_compound.add_cas_number("64-17-5")
|
||||
if hasattr(original_compound, "add_pubchem_compound_id"):
|
||||
original_compound.add_pubchem_compound_id("702")
|
||||
|
||||
mapping = dict()
|
||||
copied_compound = original_compound.copy(self.target_package, mapping)
|
||||
@ -146,7 +144,9 @@ class CopyTest(TestCase):
|
||||
self.assertEqual(original_structure.smiles, copied_structure.smiles)
|
||||
self.assertEqual(original_structure.canonical_smiles, copied_structure.canonical_smiles)
|
||||
self.assertEqual(original_structure.inchikey, copied_structure.inchikey)
|
||||
self.assertEqual(original_structure.normalized_structure, copied_structure.normalized_structure)
|
||||
self.assertEqual(
|
||||
original_structure.normalized_structure, copied_structure.normalized_structure
|
||||
)
|
||||
|
||||
# Verify they are different objects
|
||||
self.assertNotEqual(original_structure.uuid, copied_structure.uuid)
|
||||
@ -177,7 +177,9 @@ class CopyTest(TestCase):
|
||||
self.assertEqual(orig_educt.compound.package, self.package)
|
||||
self.assertEqual(orig_educt.smiles, copy_educt.smiles)
|
||||
|
||||
for orig_product, copy_product in zip(self.REACTION.products.all(), copied_reaction.products.all()):
|
||||
for orig_product, copy_product in zip(
|
||||
self.REACTION.products.all(), copied_reaction.products.all()
|
||||
):
|
||||
self.assertNotEqual(orig_product.uuid, copy_product.uuid)
|
||||
self.assertEqual(orig_product.name, copy_product.name)
|
||||
self.assertEqual(orig_product.description, copy_product.description)
|
||||
|
||||
@ -11,21 +11,21 @@ class DatasetTest(TestCase):
|
||||
def setUp(self):
|
||||
self.cs1 = Compound.create(
|
||||
self.package,
|
||||
name='2,6-Dibromohydroquinone',
|
||||
description='http://localhost:8000/package/32de3cf4-e3e6-4168-956e-32fa5ddb0ce1/compound/d6435251-1a54-4327-b4b1-fd6e9a8f4dc9/structure/d8a0225c-dbb5-4e6c-a642-730081c09c5b',
|
||||
smiles='C1=C(C(=C(C=C1O)Br)O)Br',
|
||||
name="2,6-Dibromohydroquinone",
|
||||
description="http://localhost:8000/package/32de3cf4-e3e6-4168-956e-32fa5ddb0ce1/compound/d6435251-1a54-4327-b4b1-fd6e9a8f4dc9/structure/d8a0225c-dbb5-4e6c-a642-730081c09c5b",
|
||||
smiles="C1=C(C(=C(C=C1O)Br)O)Br",
|
||||
).default_structure
|
||||
|
||||
self.cs2 = Compound.create(
|
||||
self.package,
|
||||
smiles='O=C(O)CC(=O)/C=C(/Br)C(=O)O',
|
||||
smiles="O=C(O)CC(=O)/C=C(/Br)C(=O)O",
|
||||
).default_structure
|
||||
|
||||
self.rule1 = Rule.create(
|
||||
rule_type='SimpleAmbitRule',
|
||||
rule_type="SimpleAmbitRule",
|
||||
package=self.package,
|
||||
smirks='[#8:8]([H])-[c:4]1[c:3]([H])[c:2](-[#1,#17,#35:9])[c:1](-[#8:7]([H]))[c:6](-[#1,#17,#35])[c:5]([H])1>>[#8-]-[#6:6](=O)-[#6:5]-[#6:4](=[O:8])\[#6:3]=[#6:2](\[#1,#17,#35:9])-[#6:1](-[#8-])=[O:7]',
|
||||
description='http://localhost:8000/package/32de3cf4-e3e6-4168-956e-32fa5ddb0ce1/simple-ambit-rule/f6a56c0f-a4a0-4ee3-b006-d765b4767cf6'
|
||||
smirks="[#8:8]([H])-[c:4]1[c:3]([H])[c:2](-[#1,#17,#35:9])[c:1](-[#8:7]([H]))[c:6](-[#1,#17,#35])[c:5]([H])1>>[#8-]-[#6:6](=O)-[#6:5]-[#6:4](=[O:8])\\[#6:3]=[#6:2](\\[#1,#17,#35:9])-[#6:1](-[#8-])=[O:7]",
|
||||
description="http://localhost:8000/package/32de3cf4-e3e6-4168-956e-32fa5ddb0ce1/simple-ambit-rule/f6a56c0f-a4a0-4ee3-b006-d765b4767cf6",
|
||||
)
|
||||
|
||||
self.reaction1 = Reaction.create(
|
||||
@ -33,14 +33,14 @@ class DatasetTest(TestCase):
|
||||
educts=[self.cs1],
|
||||
products=[self.cs2],
|
||||
rules=[self.rule1],
|
||||
multi_step=False
|
||||
multi_step=False,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(DatasetTest, cls).setUpClass()
|
||||
cls.user = User.objects.get(username='anonymous')
|
||||
cls.package = PackageManager.create_package(cls.user, 'Anon Test Package', 'No Desc')
|
||||
cls.user = User.objects.get(username="anonymous")
|
||||
cls.package = PackageManager.create_package(cls.user, "Anon Test Package", "No Desc")
|
||||
|
||||
def test_smoke(self):
|
||||
reactions = [r for r in Reaction.objects.filter(package=self.package)]
|
||||
|
||||
@ -1,18 +1,19 @@
|
||||
from tempfile import TemporaryDirectory
|
||||
from django.test import TestCase
|
||||
from django.test import TestCase, tag
|
||||
from epdb.logic import PackageManager
|
||||
from epdb.models import User, EnviFormer, Package
|
||||
|
||||
|
||||
@tag("slow")
|
||||
class EnviFormerTest(TestCase):
|
||||
fixtures = ["test_fixtures.jsonl.gz"]
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(EnviFormerTest, cls).setUpClass()
|
||||
cls.user = User.objects.get(username='anonymous')
|
||||
cls.package = PackageManager.create_package(cls.user, 'Anon Test Package', 'No Desc')
|
||||
cls.BBD_SUBSET = Package.objects.get(name='Fixtures')
|
||||
cls.user = User.objects.get(username="anonymous")
|
||||
cls.package = PackageManager.create_package(cls.user, "Anon Test Package", "No Desc")
|
||||
cls.BBD_SUBSET = Package.objects.get(name="Fixtures")
|
||||
|
||||
def test_model_flow(self):
|
||||
"""Test the full flow of EnviFormer, dataset build -> model finetune -> model evaluate -> model inference"""
|
||||
@ -21,11 +22,14 @@ class EnviFormerTest(TestCase):
|
||||
threshold = float(0.5)
|
||||
data_package_objs = [self.BBD_SUBSET]
|
||||
eval_packages_objs = [self.BBD_SUBSET]
|
||||
mod = EnviFormer.create(self.package, data_package_objs, eval_packages_objs, threshold=threshold)
|
||||
mod = EnviFormer.create(
|
||||
self.package, data_package_objs, eval_packages_objs, threshold=threshold
|
||||
)
|
||||
|
||||
mod.build_dataset()
|
||||
mod.build_model()
|
||||
mod.multigen_eval = True
|
||||
mod.save()
|
||||
mod.evaluate_model()
|
||||
results = mod.predict('CCN(CC)C(=O)C1=CC(=CC=C1)C')
|
||||
|
||||
mod.predict("CCN(CC)C(=O)C1=CC(=CC=C1)C")
|
||||
|
||||
@ -4,8 +4,7 @@ from utilities.chem import FormatConverter
|
||||
|
||||
|
||||
class FormatConverterTestCase(TestCase):
|
||||
|
||||
def test_standardization(self):
|
||||
smiles = 'C[n+]1c([N-](C))cccc1'
|
||||
smiles = "C[n+]1c([N-](C))cccc1"
|
||||
standardized_smiles = FormatConverter.standardize(smiles)
|
||||
self.assertEqual(standardized_smiles, 'CN=C1C=CC=CN1C')
|
||||
self.assertEqual(standardized_smiles, "CN=C1C=CC=CN1C")
|
||||
|
||||
@ -4,7 +4,7 @@ import numpy as np
|
||||
from django.test import TestCase
|
||||
|
||||
from epdb.logic import PackageManager
|
||||
from epdb.models import User, MLRelativeReasoning, RuleBasedRelativeReasoning, Package
|
||||
from epdb.models import User, MLRelativeReasoning, Package
|
||||
|
||||
|
||||
class ModelTest(TestCase):
|
||||
@ -13,9 +13,9 @@ class ModelTest(TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(ModelTest, cls).setUpClass()
|
||||
cls.user = User.objects.get(username='anonymous')
|
||||
cls.package = PackageManager.create_package(cls.user, 'Anon Test Package', 'No Desc')
|
||||
cls.BBD_SUBSET = Package.objects.get(name='Fixtures')
|
||||
cls.user = User.objects.get(username="anonymous")
|
||||
cls.package = PackageManager.create_package(cls.user, "Anon Test Package", "No Desc")
|
||||
cls.BBD_SUBSET = Package.objects.get(name="Fixtures")
|
||||
|
||||
def test_smoke(self):
|
||||
with TemporaryDirectory() as tmpdir:
|
||||
@ -32,8 +32,8 @@ class ModelTest(TestCase):
|
||||
data_package_objs,
|
||||
eval_packages_objs,
|
||||
threshold=threshold,
|
||||
name='ECC - BBD - 0.5',
|
||||
description='Created MLRelativeReasoning in Testcase',
|
||||
name="ECC - BBD - 0.5",
|
||||
description="Created MLRelativeReasoning in Testcase",
|
||||
)
|
||||
|
||||
# mod = RuleBasedRelativeReasoning.create(
|
||||
@ -54,7 +54,7 @@ class ModelTest(TestCase):
|
||||
mod.save()
|
||||
mod.evaluate_model()
|
||||
|
||||
results = mod.predict('CCN(CC)C(=O)C1=CC(=CC=C1)C')
|
||||
results = mod.predict("CCN(CC)C(=O)C1=CC(=CC=C1)C")
|
||||
|
||||
products = dict()
|
||||
for r in results:
|
||||
@ -62,8 +62,11 @@ class ModelTest(TestCase):
|
||||
products[tuple(sorted(ps.product_set))] = (r.rule.name, r.probability)
|
||||
|
||||
expected = {
|
||||
('CC=O', 'CCNC(=O)C1=CC(C)=CC=C1'): ('bt0243-4301', np.float64(0.33333333333333337)),
|
||||
('CC1=CC=CC(C(=O)O)=C1', 'CCNCC'): ('bt0430-4011', np.float64(0.25)),
|
||||
("CC=O", "CCNC(=O)C1=CC(C)=CC=C1"): (
|
||||
"bt0243-4301",
|
||||
np.float64(0.33333333333333337),
|
||||
),
|
||||
("CC1=CC=CC(C(=O)O)=C1", "CCNCC"): ("bt0430-4011", np.float64(0.25)),
|
||||
}
|
||||
|
||||
self.assertEqual(products, expected)
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import json
|
||||
from django.test import TestCase
|
||||
from networkx.utils.misc import graphs_equal
|
||||
from epdb.logic import PackageManager, SPathway
|
||||
@ -12,9 +11,11 @@ class MultiGenTest(TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(MultiGenTest, cls).setUpClass()
|
||||
cls.user: 'User' = User.objects.get(username='anonymous')
|
||||
cls.package: 'Package' = PackageManager.create_package(cls.user, 'Anon Test Package', 'No Desc')
|
||||
cls.BBD_SUBSET: 'Package' = Package.objects.get(name='Fixtures')
|
||||
cls.user: "User" = User.objects.get(username="anonymous")
|
||||
cls.package: "Package" = PackageManager.create_package(
|
||||
cls.user, "Anon Test Package", "No Desc"
|
||||
)
|
||||
cls.BBD_SUBSET: "Package" = Package.objects.get(name="Fixtures")
|
||||
|
||||
def test_equal_pathways(self):
|
||||
"""Test that two identical pathways return a precision and recall of 1.0"""
|
||||
@ -23,14 +24,23 @@ class MultiGenTest(TestCase):
|
||||
if len(pathway.edge_set.all()) == 0: # Do not test pathways with no edges
|
||||
continue
|
||||
score, precision, recall = multigen_eval(pathway, pathway)
|
||||
self.assertEqual(precision, 1.0, f"Precision should be one for identical pathways. "
|
||||
f"Failed on pathway: {pathway.name}")
|
||||
self.assertEqual(recall, 1.0, f"Recall should be one for identical pathways. "
|
||||
f"Failed on pathway: {pathway.name}")
|
||||
self.assertEqual(
|
||||
precision,
|
||||
1.0,
|
||||
f"Precision should be one for identical pathways. "
|
||||
f"Failed on pathway: {pathway.name}",
|
||||
)
|
||||
self.assertEqual(
|
||||
recall,
|
||||
1.0,
|
||||
f"Recall should be one for identical pathways. Failed on pathway: {pathway.name}",
|
||||
)
|
||||
|
||||
def test_intermediates(self):
|
||||
"""Test that an intermediate can be correctly identified and the metrics are correctly adjusted"""
|
||||
score, precision, recall, intermediates = multigen_eval(*self.intermediate_case(), return_intermediates=True)
|
||||
score, precision, recall, intermediates = multigen_eval(
|
||||
*self.intermediate_case(), return_intermediates=True
|
||||
)
|
||||
self.assertEqual(len(intermediates), 1, "There should be 1 found intermediate")
|
||||
self.assertEqual(precision, 1, "Precision should be 1")
|
||||
self.assertEqual(recall, 1, "Recall should be 1")
|
||||
@ -49,7 +59,9 @@ class MultiGenTest(TestCase):
|
||||
|
||||
def test_all(self):
|
||||
"""Test an intermediate, false-positive and false-negative together"""
|
||||
score, precision, recall, intermediates = multigen_eval(*self.all_case(), return_intermediates=True)
|
||||
score, precision, recall, intermediates = multigen_eval(
|
||||
*self.all_case(), return_intermediates=True
|
||||
)
|
||||
self.assertEqual(len(intermediates), 1, "There should be 1 found intermediate")
|
||||
self.assertAlmostEqual(precision, 0.6, 3, "Precision should be 0.6")
|
||||
self.assertAlmostEqual(recall, 0.75, 3, "Recall should be 0.75")
|
||||
@ -57,19 +69,22 @@ class MultiGenTest(TestCase):
|
||||
def test_shallow_pathway(self):
|
||||
pathways = self.BBD_SUBSET.pathways.all()
|
||||
for pathway in pathways:
|
||||
pathway_name = pathway.name
|
||||
if len(pathway.edge_set.all()) == 0: # Do not test pathways with no edges
|
||||
continue
|
||||
|
||||
shallow_pathway = graph_from_pathway(SPathway.from_pathway(pathway))
|
||||
pathway = graph_from_pathway(pathway)
|
||||
if not graphs_equal(shallow_pathway, pathway):
|
||||
print('\n\nS', shallow_pathway.adj)
|
||||
print('\n\nPW', pathway.adj)
|
||||
print("\n\nS", shallow_pathway.adj)
|
||||
print("\n\nPW", pathway.adj)
|
||||
# print(shallow_pathway.nodes, pathway.nodes)
|
||||
# print(shallow_pathway.graph, pathway.graph)
|
||||
|
||||
self.assertTrue(graphs_equal(shallow_pathway, pathway), f"Networkx graph from shallow pathway not "
|
||||
f"equal to pathway for pathway {pathway.name}")
|
||||
self.assertTrue(
|
||||
graphs_equal(shallow_pathway, pathway),
|
||||
f"Networkx graph from shallow pathway not "
|
||||
f"equal to pathway for pathway {pathway.name}",
|
||||
)
|
||||
|
||||
def test_graph_edit_eval(self):
|
||||
"""Performs all the previous tests but with graph_edit_eval
|
||||
@ -79,10 +94,16 @@ class MultiGenTest(TestCase):
|
||||
if len(pathway.edge_set.all()) == 0: # Do not test pathways with no edges
|
||||
continue
|
||||
score = pathway_edit_eval(pathway, pathway)
|
||||
self.assertEqual(score, 0.0, "Pathway edit distance should be zero for identical pathways. "
|
||||
f"Failed on pathway: {pathway.name}")
|
||||
self.assertEqual(
|
||||
score,
|
||||
0.0,
|
||||
"Pathway edit distance should be zero for identical pathways. "
|
||||
f"Failed on pathway: {pathway.name}",
|
||||
)
|
||||
inter_score = pathway_edit_eval(*self.intermediate_case())
|
||||
self.assertAlmostEqual(inter_score, 1.75, 3, "Pathway edit distance failed on intermediate case")
|
||||
self.assertAlmostEqual(
|
||||
inter_score, 1.75, 3, "Pathway edit distance failed on intermediate case"
|
||||
)
|
||||
fp_score = pathway_edit_eval(*self.fp_case())
|
||||
self.assertAlmostEqual(fp_score, 1.25, 3, "Pathway edit distance failed on fp case")
|
||||
fn_score = pathway_edit_eval(*self.fn_case())
|
||||
@ -93,22 +114,30 @@ class MultiGenTest(TestCase):
|
||||
def intermediate_case(self):
|
||||
"""Create an example with an intermediate in the predicted pathway"""
|
||||
true_pathway = Pathway.create(self.package, "CCO")
|
||||
true_pathway.add_edge([true_pathway.root_nodes.all()[0]], [true_pathway.add_node("CC(=O)O", depth=1)])
|
||||
true_pathway.add_edge(
|
||||
[true_pathway.root_nodes.all()[0]], [true_pathway.add_node("CC(=O)O", depth=1)]
|
||||
)
|
||||
pred_pathway = Pathway.create(self.package, "CCO")
|
||||
pred_pathway.add_edge([pred_pathway.root_nodes.all()[0]],
|
||||
[acetaldehyde := pred_pathway.add_node("CC=O", depth=1)])
|
||||
pred_pathway.add_edge(
|
||||
[pred_pathway.root_nodes.all()[0]],
|
||||
[acetaldehyde := pred_pathway.add_node("CC=O", depth=1)],
|
||||
)
|
||||
pred_pathway.add_edge([acetaldehyde], [pred_pathway.add_node("CC(=O)O", depth=2)])
|
||||
return true_pathway, pred_pathway
|
||||
|
||||
def fp_case(self):
|
||||
"""Create an example with an extra compound in the predicted pathway"""
|
||||
true_pathway = Pathway.create(self.package, "CCO")
|
||||
true_pathway.add_edge([true_pathway.root_nodes.all()[0]],
|
||||
[acetaldehyde := true_pathway.add_node("CC=O", depth=1)])
|
||||
true_pathway.add_edge(
|
||||
[true_pathway.root_nodes.all()[0]],
|
||||
[acetaldehyde := true_pathway.add_node("CC=O", depth=1)],
|
||||
)
|
||||
true_pathway.add_edge([acetaldehyde], [true_pathway.add_node("CC(=O)O", depth=2)])
|
||||
pred_pathway = Pathway.create(self.package, "CCO")
|
||||
pred_pathway.add_edge([pred_pathway.root_nodes.all()[0]],
|
||||
[acetaldehyde := pred_pathway.add_node("CC=O", depth=1)])
|
||||
pred_pathway.add_edge(
|
||||
[pred_pathway.root_nodes.all()[0]],
|
||||
[acetaldehyde := pred_pathway.add_node("CC=O", depth=1)],
|
||||
)
|
||||
pred_pathway.add_edge([acetaldehyde], [pred_pathway.add_node("CC(=O)O", depth=2)])
|
||||
pred_pathway.add_edge([acetaldehyde], [pred_pathway.add_node("C", depth=2)])
|
||||
return true_pathway, pred_pathway
|
||||
@ -116,22 +145,30 @@ class MultiGenTest(TestCase):
|
||||
def fn_case(self):
|
||||
"""Create an example with a missing compound in the predicted pathway"""
|
||||
true_pathway = Pathway.create(self.package, "CCO")
|
||||
true_pathway.add_edge([true_pathway.root_nodes.all()[0]],
|
||||
[acetaldehyde := true_pathway.add_node("CC=O", depth=1)])
|
||||
true_pathway.add_edge(
|
||||
[true_pathway.root_nodes.all()[0]],
|
||||
[acetaldehyde := true_pathway.add_node("CC=O", depth=1)],
|
||||
)
|
||||
true_pathway.add_edge([acetaldehyde], [true_pathway.add_node("CC(=O)O", depth=2)])
|
||||
pred_pathway = Pathway.create(self.package, "CCO")
|
||||
pred_pathway.add_edge([pred_pathway.root_nodes.all()[0]], [pred_pathway.add_node("CC=O", depth=1)])
|
||||
pred_pathway.add_edge(
|
||||
[pred_pathway.root_nodes.all()[0]], [pred_pathway.add_node("CC=O", depth=1)]
|
||||
)
|
||||
return true_pathway, pred_pathway
|
||||
|
||||
def all_case(self):
|
||||
"""Create an example with an intermediate, extra compound and missing compound"""
|
||||
true_pathway = Pathway.create(self.package, "CCO")
|
||||
true_pathway.add_edge([true_pathway.root_nodes.all()[0]],
|
||||
[acetaldehyde := true_pathway.add_node("CC=O", depth=1)])
|
||||
true_pathway.add_edge(
|
||||
[true_pathway.root_nodes.all()[0]],
|
||||
[acetaldehyde := true_pathway.add_node("CC=O", depth=1)],
|
||||
)
|
||||
true_pathway.add_edge([acetaldehyde], [true_pathway.add_node("C", depth=2)])
|
||||
true_pathway.add_edge([acetaldehyde], [true_pathway.add_node("CC(=O)O", depth=2)])
|
||||
pred_pathway = Pathway.create(self.package, "CCO")
|
||||
pred_pathway.add_edge([pred_pathway.root_nodes.all()[0]], [methane := pred_pathway.add_node("C", depth=1)])
|
||||
pred_pathway.add_edge(
|
||||
[pred_pathway.root_nodes.all()[0]], [methane := pred_pathway.add_node("C", depth=1)]
|
||||
)
|
||||
pred_pathway.add_edge([methane], [true_pathway.add_node("CC=O", depth=2)])
|
||||
pred_pathway.add_edge([methane], [true_pathway.add_node("c1ccccc1", depth=2)])
|
||||
return true_pathway, pred_pathway
|
||||
|
||||
@ -10,127 +10,127 @@ class ReactionTest(TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(ReactionTest, cls).setUpClass()
|
||||
cls.user = User.objects.get(username='anonymous')
|
||||
cls.package = PackageManager.create_package(cls.user, 'Anon Test Package', 'No Desc')
|
||||
cls.user = User.objects.get(username="anonymous")
|
||||
cls.package = PackageManager.create_package(cls.user, "Anon Test Package", "No Desc")
|
||||
|
||||
def test_smoke(self):
|
||||
educt = Compound.create(
|
||||
self.package,
|
||||
smiles='C(CCl)Cl',
|
||||
name='1,2-Dichloroethane',
|
||||
description='Eawag BBD compound c0001'
|
||||
smiles="C(CCl)Cl",
|
||||
name="1,2-Dichloroethane",
|
||||
description="Eawag BBD compound c0001",
|
||||
).default_structure
|
||||
|
||||
product = Compound.create(
|
||||
self.package,
|
||||
smiles='C(CO)Cl',
|
||||
name='2-Chloroethanol',
|
||||
description='Eawag BBD compound c0005'
|
||||
smiles="C(CO)Cl",
|
||||
name="2-Chloroethanol",
|
||||
description="Eawag BBD compound c0005",
|
||||
).default_structure
|
||||
|
||||
r = Reaction.create(
|
||||
package=self.package,
|
||||
name='Eawag BBD reaction r0001',
|
||||
name="Eawag BBD reaction r0001",
|
||||
educts=[educt],
|
||||
products=[product],
|
||||
multi_step=False
|
||||
multi_step=False,
|
||||
)
|
||||
|
||||
self.assertEqual(r.smirks(), 'C(CCl)Cl>>C(CO)Cl')
|
||||
self.assertEqual(r.name, 'Eawag BBD reaction r0001')
|
||||
self.assertEqual(r.description, 'no description')
|
||||
self.assertEqual(r.smirks(), "C(CCl)Cl>>C(CO)Cl")
|
||||
self.assertEqual(r.name, "Eawag BBD reaction r0001")
|
||||
self.assertEqual(r.description, "no description")
|
||||
|
||||
def test_string_educts_and_products(self):
|
||||
r = Reaction.create(
|
||||
package=self.package,
|
||||
name='Eawag BBD reaction r0001',
|
||||
educts=['C(CCl)Cl'],
|
||||
products=['C(CO)Cl'],
|
||||
multi_step=False
|
||||
name="Eawag BBD reaction r0001",
|
||||
educts=["C(CCl)Cl"],
|
||||
products=["C(CO)Cl"],
|
||||
multi_step=False,
|
||||
)
|
||||
|
||||
self.assertEqual(r.smirks(), 'C(CCl)Cl>>C(CO)Cl')
|
||||
self.assertEqual(r.smirks(), "C(CCl)Cl>>C(CO)Cl")
|
||||
|
||||
def test_missing_smiles(self):
|
||||
educt = Compound.create(
|
||||
self.package,
|
||||
smiles='C(CCl)Cl',
|
||||
name='1,2-Dichloroethane',
|
||||
description='Eawag BBD compound c0001'
|
||||
smiles="C(CCl)Cl",
|
||||
name="1,2-Dichloroethane",
|
||||
description="Eawag BBD compound c0001",
|
||||
).default_structure
|
||||
|
||||
product = Compound.create(
|
||||
self.package,
|
||||
smiles='C(CO)Cl',
|
||||
name='2-Chloroethanol',
|
||||
description='Eawag BBD compound c0005'
|
||||
smiles="C(CO)Cl",
|
||||
name="2-Chloroethanol",
|
||||
description="Eawag BBD compound c0005",
|
||||
).default_structure
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
_ = Reaction.create(
|
||||
package=self.package,
|
||||
name='Eawag BBD reaction r0001',
|
||||
name="Eawag BBD reaction r0001",
|
||||
educts=[educt],
|
||||
products=[],
|
||||
multi_step=False
|
||||
multi_step=False,
|
||||
)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
_ = Reaction.create(
|
||||
package=self.package,
|
||||
name='Eawag BBD reaction r0001',
|
||||
name="Eawag BBD reaction r0001",
|
||||
educts=[],
|
||||
products=[product],
|
||||
multi_step=False
|
||||
multi_step=False,
|
||||
)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
_ = Reaction.create(
|
||||
package=self.package,
|
||||
name='Eawag BBD reaction r0001',
|
||||
name="Eawag BBD reaction r0001",
|
||||
educts=[],
|
||||
products=[],
|
||||
multi_step=False
|
||||
multi_step=False,
|
||||
)
|
||||
|
||||
def test_empty_name_and_description_are_ignored(self):
|
||||
r = Reaction.create(
|
||||
package=self.package,
|
||||
name='',
|
||||
description='',
|
||||
educts=['C(CCl)Cl'],
|
||||
products=['C(CO)Cl'],
|
||||
name="",
|
||||
description="",
|
||||
educts=["C(CCl)Cl"],
|
||||
products=["C(CO)Cl"],
|
||||
multi_step=False,
|
||||
)
|
||||
|
||||
self.assertEqual(r.name, 'no name')
|
||||
self.assertEqual(r.description, 'no description')
|
||||
self.assertEqual(r.name, "no name")
|
||||
self.assertEqual(r.description, "no description")
|
||||
|
||||
def test_deduplication(self):
|
||||
rule = Rule.create(
|
||||
package=self.package,
|
||||
rule_type='SimpleAmbitRule',
|
||||
name='bt0022-2833',
|
||||
description='Dihalomethyl derivative + Halomethyl derivative > 1-Halo-1-methylalcohol derivative + 1-Methylalcohol derivative',
|
||||
smirks='[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]',
|
||||
rule_type="SimpleAmbitRule",
|
||||
name="bt0022-2833",
|
||||
description="Dihalomethyl derivative + Halomethyl derivative > 1-Halo-1-methylalcohol derivative + 1-Methylalcohol derivative",
|
||||
smirks="[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]",
|
||||
)
|
||||
|
||||
r1 = Reaction.create(
|
||||
package=self.package,
|
||||
name='Eawag BBD reaction r0001',
|
||||
educts=['C(CCl)Cl'],
|
||||
products=['C(CO)Cl'],
|
||||
name="Eawag BBD reaction r0001",
|
||||
educts=["C(CCl)Cl"],
|
||||
products=["C(CO)Cl"],
|
||||
rules=[rule],
|
||||
multi_step=False
|
||||
multi_step=False,
|
||||
)
|
||||
|
||||
r2 = Reaction.create(
|
||||
package=self.package,
|
||||
name='Eawag BBD reaction r0001',
|
||||
educts=['C(CCl)Cl'],
|
||||
products=['C(CO)Cl'],
|
||||
name="Eawag BBD reaction r0001",
|
||||
educts=["C(CCl)Cl"],
|
||||
products=["C(CO)Cl"],
|
||||
rules=[rule],
|
||||
multi_step=False
|
||||
multi_step=False,
|
||||
)
|
||||
|
||||
# Check if create detects that this Compound already exist
|
||||
@ -141,18 +141,18 @@ class ReactionTest(TestCase):
|
||||
def test_deduplication_without_rules(self):
|
||||
r1 = Reaction.create(
|
||||
package=self.package,
|
||||
name='Eawag BBD reaction r0001',
|
||||
educts=['C(CCl)Cl'],
|
||||
products=['C(CO)Cl'],
|
||||
multi_step=False
|
||||
name="Eawag BBD reaction r0001",
|
||||
educts=["C(CCl)Cl"],
|
||||
products=["C(CO)Cl"],
|
||||
multi_step=False,
|
||||
)
|
||||
|
||||
r2 = Reaction.create(
|
||||
package=self.package,
|
||||
name='Eawag BBD reaction r0001',
|
||||
educts=['C(CCl)Cl'],
|
||||
products=['C(CO)Cl'],
|
||||
multi_step=False
|
||||
name="Eawag BBD reaction r0001",
|
||||
educts=["C(CCl)Cl"],
|
||||
products=["C(CO)Cl"],
|
||||
multi_step=False,
|
||||
)
|
||||
|
||||
# Check if create detects that this Compound already exist
|
||||
@ -164,19 +164,19 @@ class ReactionTest(TestCase):
|
||||
with self.assertRaises(ValueError):
|
||||
_ = Reaction.create(
|
||||
package=self.package,
|
||||
name='Eawag BBD reaction r0001',
|
||||
educts=['ASDF'],
|
||||
products=['C(CO)Cl'],
|
||||
multi_step=False
|
||||
name="Eawag BBD reaction r0001",
|
||||
educts=["ASDF"],
|
||||
products=["C(CO)Cl"],
|
||||
multi_step=False,
|
||||
)
|
||||
|
||||
def test_delete(self):
|
||||
r = Reaction.create(
|
||||
package=self.package,
|
||||
name='Eawag BBD reaction r0001',
|
||||
educts=['C(CCl)Cl'],
|
||||
products=['C(CO)Cl'],
|
||||
multi_step=False
|
||||
name="Eawag BBD reaction r0001",
|
||||
educts=["C(CCl)Cl"],
|
||||
products=["C(CO)Cl"],
|
||||
multi_step=False,
|
||||
)
|
||||
|
||||
r.delete()
|
||||
|
||||
@ -10,73 +10,79 @@ class RuleTest(TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(RuleTest, cls).setUpClass()
|
||||
cls.user = User.objects.get(username='anonymous')
|
||||
cls.package = PackageManager.create_package(cls.user, 'Anon Test Package', 'No Desc')
|
||||
cls.user = User.objects.get(username="anonymous")
|
||||
cls.package = PackageManager.create_package(cls.user, "Anon Test Package", "No Desc")
|
||||
|
||||
def test_smoke(self):
|
||||
r = Rule.create(
|
||||
rule_type='SimpleAmbitRule',
|
||||
rule_type="SimpleAmbitRule",
|
||||
package=self.package,
|
||||
name='bt0022-2833',
|
||||
description='Dihalomethyl derivative + Halomethyl derivative > 1-Halo-1-methylalcohol derivative + 1-Methylalcohol derivative',
|
||||
smirks='[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]',
|
||||
name="bt0022-2833",
|
||||
description="Dihalomethyl derivative + Halomethyl derivative > 1-Halo-1-methylalcohol derivative + 1-Methylalcohol derivative",
|
||||
smirks="[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]",
|
||||
)
|
||||
|
||||
self.assertEqual(r.smirks,
|
||||
'[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]')
|
||||
self.assertEqual(r.name, 'bt0022-2833')
|
||||
self.assertEqual(r.description,
|
||||
'Dihalomethyl derivative + Halomethyl derivative > 1-Halo-1-methylalcohol derivative + 1-Methylalcohol derivative')
|
||||
self.assertEqual(
|
||||
r.smirks,
|
||||
"[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]",
|
||||
)
|
||||
self.assertEqual(r.name, "bt0022-2833")
|
||||
self.assertEqual(
|
||||
r.description,
|
||||
"Dihalomethyl derivative + Halomethyl derivative > 1-Halo-1-methylalcohol derivative + 1-Methylalcohol derivative",
|
||||
)
|
||||
|
||||
def test_smirks_are_trimmed(self):
|
||||
r = Rule.create(
|
||||
rule_type='SimpleAmbitRule',
|
||||
rule_type="SimpleAmbitRule",
|
||||
package=self.package,
|
||||
name='bt0022-2833',
|
||||
description='Dihalomethyl derivative + Halomethyl derivative > 1-Halo-1-methylalcohol derivative + 1-Methylalcohol derivative',
|
||||
smirks=' [H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4] ',
|
||||
name="bt0022-2833",
|
||||
description="Dihalomethyl derivative + Halomethyl derivative > 1-Halo-1-methylalcohol derivative + 1-Methylalcohol derivative",
|
||||
smirks=" [H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4] ",
|
||||
)
|
||||
|
||||
self.assertEqual(r.smirks,
|
||||
'[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]')
|
||||
self.assertEqual(
|
||||
r.smirks,
|
||||
"[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]",
|
||||
)
|
||||
|
||||
def test_name_and_description_optional(self):
|
||||
r = Rule.create(
|
||||
rule_type='SimpleAmbitRule',
|
||||
rule_type="SimpleAmbitRule",
|
||||
package=self.package,
|
||||
smirks='[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]',
|
||||
smirks="[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]",
|
||||
)
|
||||
|
||||
self.assertRegex(r.name, 'Rule \\d+')
|
||||
self.assertEqual(r.description, 'no description')
|
||||
self.assertRegex(r.name, "Rule \\d+")
|
||||
self.assertEqual(r.description, "no description")
|
||||
|
||||
def test_empty_name_and_description_are_ignored(self):
|
||||
r = Rule.create(
|
||||
rule_type='SimpleAmbitRule',
|
||||
rule_type="SimpleAmbitRule",
|
||||
package=self.package,
|
||||
smirks='[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]',
|
||||
name='',
|
||||
description='',
|
||||
smirks="[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]",
|
||||
name="",
|
||||
description="",
|
||||
)
|
||||
|
||||
self.assertRegex(r.name, 'Rule \\d+')
|
||||
self.assertEqual(r.description, 'no description')
|
||||
self.assertRegex(r.name, "Rule \\d+")
|
||||
self.assertEqual(r.description, "no description")
|
||||
|
||||
def test_deduplication(self):
|
||||
r1 = Rule.create(
|
||||
rule_type='SimpleAmbitRule',
|
||||
rule_type="SimpleAmbitRule",
|
||||
package=self.package,
|
||||
smirks='[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]',
|
||||
name='',
|
||||
description='',
|
||||
smirks="[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]",
|
||||
name="",
|
||||
description="",
|
||||
)
|
||||
|
||||
r2 = Rule.create(
|
||||
rule_type='SimpleAmbitRule',
|
||||
rule_type="SimpleAmbitRule",
|
||||
package=self.package,
|
||||
smirks='[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]',
|
||||
name='',
|
||||
description='',
|
||||
smirks="[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]",
|
||||
name="",
|
||||
description="",
|
||||
)
|
||||
|
||||
self.assertEqual(r1.pk, r2.pk)
|
||||
@ -84,21 +90,21 @@ class RuleTest(TestCase):
|
||||
|
||||
def test_valid_smirks(self):
|
||||
with self.assertRaises(ValueError):
|
||||
r = Rule.create(
|
||||
rule_type='SimpleAmbitRule',
|
||||
Rule.create(
|
||||
rule_type="SimpleAmbitRule",
|
||||
package=self.package,
|
||||
smirks='This is not a valid SMIRKS',
|
||||
name='',
|
||||
description='',
|
||||
smirks="This is not a valid SMIRKS",
|
||||
name="",
|
||||
description="",
|
||||
)
|
||||
|
||||
def test_delete(self):
|
||||
r = Rule.create(
|
||||
rule_type='SimpleAmbitRule',
|
||||
rule_type="SimpleAmbitRule",
|
||||
package=self.package,
|
||||
smirks='[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]',
|
||||
name='',
|
||||
description='',
|
||||
smirks="[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]",
|
||||
name="",
|
||||
description="",
|
||||
)
|
||||
|
||||
r.delete()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -12,34 +12,32 @@ class SimpleAmbitRuleTest(TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(SimpleAmbitRuleTest, cls).setUpClass()
|
||||
cls.user = User.objects.get(username='anonymous')
|
||||
cls.package = PackageManager.create_package(cls.user, 'Simple Ambit Rule Test Package',
|
||||
'Test Package for SimpleAmbitRule')
|
||||
cls.user = User.objects.get(username="anonymous")
|
||||
cls.package = PackageManager.create_package(
|
||||
cls.user, "Simple Ambit Rule Test Package", "Test Package for SimpleAmbitRule"
|
||||
)
|
||||
|
||||
def test_create_basic_rule(self):
|
||||
"""Test creating a basic SimpleAmbitRule with minimal parameters."""
|
||||
smirks = '[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]'
|
||||
smirks = "[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]"
|
||||
|
||||
rule = SimpleAmbitRule.create(
|
||||
package=self.package,
|
||||
smirks=smirks
|
||||
)
|
||||
rule = SimpleAmbitRule.create(package=self.package, smirks=smirks)
|
||||
|
||||
self.assertIsInstance(rule, SimpleAmbitRule)
|
||||
self.assertEqual(rule.smirks, smirks)
|
||||
self.assertEqual(rule.package, self.package)
|
||||
self.assertRegex(rule.name, r'Rule \d+')
|
||||
self.assertEqual(rule.description, 'no description')
|
||||
self.assertRegex(rule.name, r"Rule \d+")
|
||||
self.assertEqual(rule.description, "no description")
|
||||
self.assertIsNone(rule.reactant_filter_smarts)
|
||||
self.assertIsNone(rule.product_filter_smarts)
|
||||
|
||||
def test_create_with_all_parameters(self):
|
||||
"""Test creating SimpleAmbitRule with all parameters."""
|
||||
smirks = '[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]'
|
||||
name = 'Test Rule'
|
||||
description = 'A test biotransformation rule'
|
||||
reactant_filter = '[CH2X4]'
|
||||
product_filter = '[OH]'
|
||||
smirks = "[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]"
|
||||
name = "Test Rule"
|
||||
description = "A test biotransformation rule"
|
||||
reactant_filter = "[CH2X4]"
|
||||
product_filter = "[OH]"
|
||||
|
||||
rule = SimpleAmbitRule.create(
|
||||
package=self.package,
|
||||
@ -47,7 +45,7 @@ class SimpleAmbitRuleTest(TestCase):
|
||||
description=description,
|
||||
smirks=smirks,
|
||||
reactant_filter_smarts=reactant_filter,
|
||||
product_filter_smarts=product_filter
|
||||
product_filter_smarts=product_filter,
|
||||
)
|
||||
|
||||
self.assertEqual(rule.name, name)
|
||||
@ -60,127 +58,114 @@ class SimpleAmbitRuleTest(TestCase):
|
||||
"""Test that SMIRKS is required for rule creation."""
|
||||
with self.assertRaises(ValueError) as cm:
|
||||
SimpleAmbitRule.create(package=self.package, smirks=None)
|
||||
self.assertIn('SMIRKS is required', str(cm.exception))
|
||||
self.assertIn("SMIRKS is required", str(cm.exception))
|
||||
|
||||
with self.assertRaises(ValueError) as cm:
|
||||
SimpleAmbitRule.create(package=self.package, smirks='')
|
||||
self.assertIn('SMIRKS is required', str(cm.exception))
|
||||
SimpleAmbitRule.create(package=self.package, smirks="")
|
||||
self.assertIn("SMIRKS is required", str(cm.exception))
|
||||
|
||||
with self.assertRaises(ValueError) as cm:
|
||||
SimpleAmbitRule.create(package=self.package, smirks=' ')
|
||||
self.assertIn('SMIRKS is required', str(cm.exception))
|
||||
SimpleAmbitRule.create(package=self.package, smirks=" ")
|
||||
self.assertIn("SMIRKS is required", str(cm.exception))
|
||||
|
||||
@patch('epdb.models.FormatConverter.is_valid_smirks')
|
||||
@patch("epdb.models.FormatConverter.is_valid_smirks")
|
||||
def test_invalid_smirks_validation(self, mock_is_valid):
|
||||
"""Test validation of SMIRKS format."""
|
||||
mock_is_valid.return_value = False
|
||||
|
||||
invalid_smirks = 'invalid_smirks_string'
|
||||
invalid_smirks = "invalid_smirks_string"
|
||||
with self.assertRaises(ValueError) as cm:
|
||||
SimpleAmbitRule.create(
|
||||
package=self.package,
|
||||
smirks=invalid_smirks
|
||||
)
|
||||
SimpleAmbitRule.create(package=self.package, smirks=invalid_smirks)
|
||||
|
||||
self.assertIn(f'SMIRKS "{invalid_smirks}" is invalid', str(cm.exception))
|
||||
mock_is_valid.assert_called_once_with(invalid_smirks)
|
||||
|
||||
def test_smirks_trimming(self):
|
||||
"""Test that SMIRKS strings are trimmed during creation."""
|
||||
smirks = '[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]'
|
||||
smirks_with_whitespace = f' {smirks} '
|
||||
smirks = "[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]"
|
||||
smirks_with_whitespace = f" {smirks} "
|
||||
|
||||
rule = SimpleAmbitRule.create(
|
||||
package=self.package,
|
||||
smirks=smirks_with_whitespace
|
||||
)
|
||||
rule = SimpleAmbitRule.create(package=self.package, smirks=smirks_with_whitespace)
|
||||
|
||||
self.assertEqual(rule.smirks, smirks)
|
||||
|
||||
def test_empty_name_and_description_handling(self):
|
||||
"""Test that empty name and description are handled appropriately."""
|
||||
smirks = '[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]'
|
||||
smirks = "[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]"
|
||||
|
||||
rule = SimpleAmbitRule.create(
|
||||
package=self.package,
|
||||
smirks=smirks,
|
||||
name='',
|
||||
description=' '
|
||||
package=self.package, smirks=smirks, name="", description=" "
|
||||
)
|
||||
|
||||
self.assertRegex(rule.name, r'Rule \d+')
|
||||
self.assertEqual(rule.description, 'no description')
|
||||
self.assertRegex(rule.name, r"Rule \d+")
|
||||
self.assertEqual(rule.description, "no description")
|
||||
|
||||
def test_deduplication_basic(self):
|
||||
"""Test that identical rules are deduplicated."""
|
||||
smirks = '[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]'
|
||||
smirks = "[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]"
|
||||
|
||||
rule1 = SimpleAmbitRule.create(
|
||||
package=self.package,
|
||||
smirks=smirks,
|
||||
name='Rule 1'
|
||||
)
|
||||
rule1 = SimpleAmbitRule.create(package=self.package, smirks=smirks, name="Rule 1")
|
||||
|
||||
rule2 = SimpleAmbitRule.create(
|
||||
package=self.package,
|
||||
smirks=smirks,
|
||||
name='Rule 2' # Different name, but same SMIRKS
|
||||
name="Rule 2", # Different name, but same SMIRKS
|
||||
)
|
||||
|
||||
self.assertEqual(rule1.pk, rule2.pk)
|
||||
self.assertEqual(SimpleAmbitRule.objects.filter(package=self.package, smirks=smirks).count(), 1)
|
||||
self.assertEqual(
|
||||
SimpleAmbitRule.objects.filter(package=self.package, smirks=smirks).count(), 1
|
||||
)
|
||||
|
||||
def test_deduplication_with_filters(self):
|
||||
"""Test deduplication with filter SMARTS."""
|
||||
smirks = '[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]'
|
||||
reactant_filter = '[CH2X4]'
|
||||
product_filter = '[OH]'
|
||||
smirks = "[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]"
|
||||
reactant_filter = "[CH2X4]"
|
||||
product_filter = "[OH]"
|
||||
|
||||
rule1 = SimpleAmbitRule.create(
|
||||
package=self.package,
|
||||
smirks=smirks,
|
||||
reactant_filter_smarts=reactant_filter,
|
||||
product_filter_smarts=product_filter
|
||||
product_filter_smarts=product_filter,
|
||||
)
|
||||
|
||||
rule2 = SimpleAmbitRule.create(
|
||||
package=self.package,
|
||||
smirks=smirks,
|
||||
reactant_filter_smarts=reactant_filter,
|
||||
product_filter_smarts=product_filter
|
||||
product_filter_smarts=product_filter,
|
||||
)
|
||||
|
||||
self.assertEqual(rule1.pk, rule2.pk)
|
||||
|
||||
def test_no_deduplication_different_filters(self):
|
||||
"""Test that rules with different filters are not deduplicated."""
|
||||
smirks = '[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]'
|
||||
smirks = "[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]"
|
||||
|
||||
rule1 = SimpleAmbitRule.create(
|
||||
package=self.package,
|
||||
smirks=smirks,
|
||||
reactant_filter_smarts='[CH2X4]'
|
||||
package=self.package, smirks=smirks, reactant_filter_smarts="[CH2X4]"
|
||||
)
|
||||
|
||||
rule2 = SimpleAmbitRule.create(
|
||||
package=self.package,
|
||||
smirks=smirks,
|
||||
reactant_filter_smarts='[CH3X4]'
|
||||
package=self.package, smirks=smirks, reactant_filter_smarts="[CH3X4]"
|
||||
)
|
||||
|
||||
self.assertNotEqual(rule1.pk, rule2.pk)
|
||||
self.assertEqual(SimpleAmbitRule.objects.filter(package=self.package, smirks=smirks).count(), 2)
|
||||
self.assertEqual(
|
||||
SimpleAmbitRule.objects.filter(package=self.package, smirks=smirks).count(), 2
|
||||
)
|
||||
|
||||
def test_filter_smarts_trimming(self):
|
||||
"""Test that filter SMARTS are trimmed and handled correctly."""
|
||||
smirks = '[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]'
|
||||
smirks = "[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]"
|
||||
|
||||
# Test with whitespace-only filters (should be treated as None)
|
||||
rule = SimpleAmbitRule.create(
|
||||
package=self.package,
|
||||
smirks=smirks,
|
||||
reactant_filter_smarts=' ',
|
||||
product_filter_smarts=' '
|
||||
reactant_filter_smarts=" ",
|
||||
product_filter_smarts=" ",
|
||||
)
|
||||
|
||||
self.assertIsNone(rule.reactant_filter_smarts)
|
||||
@ -188,94 +173,85 @@ class SimpleAmbitRuleTest(TestCase):
|
||||
|
||||
def test_url_property(self):
|
||||
"""Test the URL property generation."""
|
||||
rule = SimpleAmbitRule.create(
|
||||
package=self.package,
|
||||
smirks='[H:1][C:2]>>[H:1][O:2]'
|
||||
)
|
||||
rule = SimpleAmbitRule.create(package=self.package, smirks="[H:1][C:2]>>[H:1][O:2]")
|
||||
|
||||
expected_url = f'{self.package.url}/simple-ambit-rule/{rule.uuid}'
|
||||
expected_url = f"{self.package.url}/simple-ambit-rule/{rule.uuid}"
|
||||
self.assertEqual(rule.url, expected_url)
|
||||
|
||||
@patch('epdb.models.FormatConverter.apply')
|
||||
@patch("epdb.models.FormatConverter.apply")
|
||||
def test_apply_method(self, mock_apply):
|
||||
"""Test the apply method delegates to FormatConverter."""
|
||||
mock_apply.return_value = ['product1', 'product2']
|
||||
mock_apply.return_value = ["product1", "product2"]
|
||||
|
||||
rule = SimpleAmbitRule.create(
|
||||
package=self.package,
|
||||
smirks='[H:1][C:2]>>[H:1][O:2]'
|
||||
)
|
||||
rule = SimpleAmbitRule.create(package=self.package, smirks="[H:1][C:2]>>[H:1][O:2]")
|
||||
|
||||
test_smiles = 'CCO'
|
||||
test_smiles = "CCO"
|
||||
result = rule.apply(test_smiles)
|
||||
|
||||
mock_apply.assert_called_once_with(test_smiles, rule.smirks)
|
||||
self.assertEqual(result, ['product1', 'product2'])
|
||||
self.assertEqual(result, ["product1", "product2"])
|
||||
|
||||
def test_reactants_smarts_property(self):
|
||||
"""Test reactants_smarts property extracts correct part of SMIRKS."""
|
||||
smirks = '[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]'
|
||||
expected_reactants = '[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]'
|
||||
smirks = "[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]"
|
||||
expected_reactants = "[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]"
|
||||
|
||||
rule = SimpleAmbitRule.create(
|
||||
package=self.package,
|
||||
smirks=smirks
|
||||
)
|
||||
rule = SimpleAmbitRule.create(package=self.package, smirks=smirks)
|
||||
|
||||
self.assertEqual(rule.reactants_smarts, expected_reactants)
|
||||
|
||||
def test_products_smarts_property(self):
|
||||
"""Test products_smarts property extracts correct part of SMIRKS."""
|
||||
smirks = '[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]'
|
||||
expected_products = '[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]'
|
||||
smirks = "[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]"
|
||||
expected_products = "[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]"
|
||||
|
||||
rule = SimpleAmbitRule.create(
|
||||
package=self.package,
|
||||
smirks=smirks
|
||||
)
|
||||
rule = SimpleAmbitRule.create(package=self.package, smirks=smirks)
|
||||
|
||||
self.assertEqual(rule.products_smarts, expected_products)
|
||||
|
||||
@patch('epdb.models.Package.objects')
|
||||
@patch("epdb.models.Package.objects")
|
||||
def test_related_reactions_property(self, mock_package_objects):
|
||||
"""Test related_reactions property returns correct queryset."""
|
||||
mock_qs = MagicMock()
|
||||
mock_package_objects.filter.return_value = mock_qs
|
||||
|
||||
rule = SimpleAmbitRule.create(
|
||||
package=self.package,
|
||||
smirks='[H:1][C:2]>>[H:1][O:2]'
|
||||
)
|
||||
rule = SimpleAmbitRule.create(package=self.package, smirks="[H:1][C:2]>>[H:1][O:2]")
|
||||
|
||||
# Instead of directly assigning, patch the property or use with patch.object
|
||||
with patch.object(type(rule), 'reaction_rule', new_callable=PropertyMock) as mock_reaction_rule:
|
||||
mock_reaction_rule.return_value.filter.return_value.order_by.return_value = ['reaction1', 'reaction2']
|
||||
with patch.object(
|
||||
type(rule), "reaction_rule", new_callable=PropertyMock
|
||||
) as mock_reaction_rule:
|
||||
mock_reaction_rule.return_value.filter.return_value.order_by.return_value = [
|
||||
"reaction1",
|
||||
"reaction2",
|
||||
]
|
||||
|
||||
result = rule.related_reactions
|
||||
|
||||
mock_package_objects.filter.assert_called_once_with(reviewed=True)
|
||||
mock_reaction_rule.return_value.filter.assert_called_once_with(package__in=mock_qs)
|
||||
mock_reaction_rule.return_value.filter.return_value.order_by.assert_called_once_with('name')
|
||||
self.assertEqual(result, ['reaction1', 'reaction2'])
|
||||
mock_reaction_rule.return_value.filter.return_value.order_by.assert_called_once_with(
|
||||
"name"
|
||||
)
|
||||
self.assertEqual(result, ["reaction1", "reaction2"])
|
||||
|
||||
@patch('epdb.models.Pathway.objects')
|
||||
@patch('epdb.models.Edge.objects')
|
||||
@patch("epdb.models.Pathway.objects")
|
||||
@patch("epdb.models.Edge.objects")
|
||||
def test_related_pathways_property(self, mock_edge_objects, mock_pathway_objects):
|
||||
"""Test related_pathways property returns correct queryset."""
|
||||
|
||||
mock_related_reactions = ['reaction1', 'reaction2']
|
||||
mock_related_reactions = ["reaction1", "reaction2"]
|
||||
|
||||
with patch.object(SimpleAmbitRule, "related_reactions", new_callable=PropertyMock) as mock_prop:
|
||||
with patch.object(
|
||||
SimpleAmbitRule, "related_reactions", new_callable=PropertyMock
|
||||
) as mock_prop:
|
||||
mock_prop.return_value = mock_related_reactions
|
||||
|
||||
rule = SimpleAmbitRule.create(
|
||||
package=self.package,
|
||||
smirks='[H:1][C:2]>>[H:1][O:2]'
|
||||
)
|
||||
rule = SimpleAmbitRule.create(package=self.package, smirks="[H:1][C:2]>>[H:1][O:2]")
|
||||
|
||||
# Mock Edge objects query
|
||||
mock_edge_values = MagicMock()
|
||||
mock_edge_values.values.return_value = ['pathway_id1', 'pathway_id2']
|
||||
mock_edge_values.values.return_value = ["pathway_id1", "pathway_id2"]
|
||||
mock_edge_objects.filter.return_value = mock_edge_values
|
||||
|
||||
# Mock Pathway objects query
|
||||
@ -285,52 +261,49 @@ class SimpleAmbitRuleTest(TestCase):
|
||||
result = rule.related_pathways
|
||||
|
||||
mock_edge_objects.filter.assert_called_once_with(edge_label__in=mock_related_reactions)
|
||||
mock_edge_values.values.assert_called_once_with('pathway_id')
|
||||
mock_edge_values.values.assert_called_once_with("pathway_id")
|
||||
mock_pathway_objects.filter.assert_called_once()
|
||||
self.assertEqual(result, mock_pathway_qs)
|
||||
|
||||
@patch('epdb.models.IndigoUtils.smirks_to_svg')
|
||||
@patch("epdb.models.IndigoUtils.smirks_to_svg")
|
||||
def test_as_svg_property(self, mock_smirks_to_svg):
|
||||
"""Test as_svg property calls IndigoUtils correctly."""
|
||||
mock_smirks_to_svg.return_value = '<svg>test_svg</svg>'
|
||||
mock_smirks_to_svg.return_value = "<svg>test_svg</svg>"
|
||||
|
||||
rule = SimpleAmbitRule.create(
|
||||
package=self.package,
|
||||
smirks='[H:1][C:2]>>[H:1][O:2]'
|
||||
)
|
||||
rule = SimpleAmbitRule.create(package=self.package, smirks="[H:1][C:2]>>[H:1][O:2]")
|
||||
|
||||
result = rule.as_svg
|
||||
mock_smirks_to_svg.assert_called_once_with(rule.smirks, True, width=800, height=400)
|
||||
self.assertEqual(result, '<svg>test_svg</svg>')
|
||||
self.assertEqual(result, "<svg>test_svg</svg>")
|
||||
|
||||
def test_atomic_transaction(self):
|
||||
"""Test that rule creation is atomic."""
|
||||
smirks = '[H:1][C:2]>>[H:1][O:2]'
|
||||
smirks = "[H:1][C:2]>>[H:1][O:2]"
|
||||
|
||||
# This should work normally
|
||||
rule = SimpleAmbitRule.create(package=self.package, smirks=smirks)
|
||||
self.assertIsInstance(rule, SimpleAmbitRule)
|
||||
|
||||
# Test transaction rollback on error
|
||||
with patch('epdb.models.SimpleAmbitRule.save', side_effect=Exception('Database error')):
|
||||
with patch("epdb.models.SimpleAmbitRule.save", side_effect=Exception("Database error")):
|
||||
with self.assertRaises(Exception):
|
||||
SimpleAmbitRule.create(package=self.package, smirks='[H:3][C:4]>>[H:3][O:4]')
|
||||
SimpleAmbitRule.create(package=self.package, smirks="[H:3][C:4]>>[H:3][O:4]")
|
||||
|
||||
# Verify no partial data was saved
|
||||
self.assertEqual(SimpleAmbitRule.objects.filter(package=self.package).count(), 1)
|
||||
|
||||
def test_multiple_duplicate_warning(self):
|
||||
"""Test logging when multiple duplicates are found."""
|
||||
smirks = '[H:1][C:2]>>[H:1][O:2]'
|
||||
smirks = "[H:1][C:2]>>[H:1][O:2]"
|
||||
|
||||
# Create first rule
|
||||
rule1 = SimpleAmbitRule.create(package=self.package, smirks=smirks)
|
||||
|
||||
# Manually create a duplicate to simulate the error condition
|
||||
rule2 = SimpleAmbitRule(package=self.package, smirks=smirks, name='Manual Rule')
|
||||
rule2 = SimpleAmbitRule(package=self.package, smirks=smirks, name="Manual Rule")
|
||||
rule2.save()
|
||||
|
||||
with patch('epdb.models.logger') as mock_logger:
|
||||
with patch("epdb.models.logger") as mock_logger:
|
||||
# This should find the existing rule and log an error about multiple matches
|
||||
result = SimpleAmbitRule.create(package=self.package, smirks=smirks)
|
||||
|
||||
@ -339,24 +312,28 @@ class SimpleAmbitRuleTest(TestCase):
|
||||
|
||||
# Should log an error about multiple matches
|
||||
mock_logger.error.assert_called()
|
||||
self.assertIn('More than one rule matched', mock_logger.error.call_args[0][0])
|
||||
self.assertIn("More than one rule matched", mock_logger.error.call_args[0][0])
|
||||
|
||||
def test_model_fields(self):
|
||||
"""Test model field properties."""
|
||||
rule = SimpleAmbitRule.create(
|
||||
package=self.package,
|
||||
smirks='[H:1][C:2]>>[H:1][O:2]',
|
||||
reactant_filter_smarts='[CH3]',
|
||||
product_filter_smarts='[OH]'
|
||||
smirks="[H:1][C:2]>>[H:1][O:2]",
|
||||
reactant_filter_smarts="[CH3]",
|
||||
product_filter_smarts="[OH]",
|
||||
)
|
||||
|
||||
# Test field properties
|
||||
self.assertFalse(rule._meta.get_field('smirks').blank)
|
||||
self.assertFalse(rule._meta.get_field('smirks').null)
|
||||
self.assertTrue(rule._meta.get_field('reactant_filter_smarts').null)
|
||||
self.assertTrue(rule._meta.get_field('product_filter_smarts').null)
|
||||
self.assertFalse(rule._meta.get_field("smirks").blank)
|
||||
self.assertFalse(rule._meta.get_field("smirks").null)
|
||||
self.assertTrue(rule._meta.get_field("reactant_filter_smarts").null)
|
||||
self.assertTrue(rule._meta.get_field("product_filter_smarts").null)
|
||||
|
||||
# Test verbose names
|
||||
self.assertEqual(rule._meta.get_field('smirks').verbose_name, 'SMIRKS')
|
||||
self.assertEqual(rule._meta.get_field('reactant_filter_smarts').verbose_name, 'Reactant Filter SMARTS')
|
||||
self.assertEqual(rule._meta.get_field('product_filter_smarts').verbose_name, 'Product Filter SMARTS')
|
||||
self.assertEqual(rule._meta.get_field("smirks").verbose_name, "SMIRKS")
|
||||
self.assertEqual(
|
||||
rule._meta.get_field("reactant_filter_smarts").verbose_name, "Reactant Filter SMARTS"
|
||||
)
|
||||
self.assertEqual(
|
||||
rule._meta.get_field("product_filter_smarts").verbose_name, "Product Filter SMARTS"
|
||||
)
|
||||
|
||||
@ -1,32 +1,29 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from epdb.logic import SNode, SEdge, SPathway
|
||||
from epdb.logic import SNode, SEdge
|
||||
|
||||
|
||||
class SObjectTest(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
pass
|
||||
|
||||
def test_snode_eq(self):
|
||||
snode1 = SNode('CN1C2C(N(C(N(C)C=2N=C1)=O)C)=O', 0)
|
||||
snode2 = SNode('CN1C2C(N(C(N(C)C=2N=C1)=O)C)=O', 0)
|
||||
snode1 = SNode("CN1C2C(N(C(N(C)C=2N=C1)=O)C)=O", 0)
|
||||
snode2 = SNode("CN1C2C(N(C(N(C)C=2N=C1)=O)C)=O", 0)
|
||||
assert snode1 == snode2
|
||||
|
||||
def test_snode_hash(self):
|
||||
pass
|
||||
|
||||
def test_sedge_eq(self):
|
||||
sedge1 = SEdge([SNode('CN1C2C(N(C(N(C)C=2N=C1)=O)C)=O', 0)],
|
||||
[SNode('CN1C(=O)NC2=C(C1=O)N(C)C=N2', 1), SNode('C=O', 1)],
|
||||
rule=None)
|
||||
sedge2 = SEdge([SNode('CN1C2C(N(C(N(C)C=2N=C1)=O)C)=O', 0)],
|
||||
[SNode('CN1C(=O)NC2=C(C1=O)N(C)C=N2', 1), SNode('C=O', 1)],
|
||||
rule=None)
|
||||
sedge1 = SEdge(
|
||||
[SNode("CN1C2C(N(C(N(C)C=2N=C1)=O)C)=O", 0)],
|
||||
[SNode("CN1C(=O)NC2=C(C1=O)N(C)C=N2", 1), SNode("C=O", 1)],
|
||||
rule=None,
|
||||
)
|
||||
sedge2 = SEdge(
|
||||
[SNode("CN1C2C(N(C(N(C)C=2N=C1)=O)C)=O", 0)],
|
||||
[SNode("CN1C(=O)NC2=C(C1=O)N(C)C=N2", 1), SNode("C=O", 1)],
|
||||
rule=None,
|
||||
)
|
||||
assert sedge1 == sedge2
|
||||
|
||||
def test_sedge_hash(self):
|
||||
pass
|
||||
|
||||
def test_spathway(self):
|
||||
pw = SPathway()
|
||||
|
||||
@ -3,7 +3,7 @@ from django.urls import reverse
|
||||
from envipy_additional_information import Temperature, Interval
|
||||
|
||||
from epdb.logic import UserManager, PackageManager
|
||||
from epdb.models import Compound, Scenario, ExternalIdentifier, ExternalDatabase
|
||||
from epdb.models import Compound, Scenario, ExternalDatabase
|
||||
|
||||
|
||||
class CompoundViewTest(TestCase):
|
||||
@ -12,21 +12,28 @@ class CompoundViewTest(TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(CompoundViewTest, cls).setUpClass()
|
||||
cls.user1 = UserManager.create_user("user1", "user1@envipath.com", "SuperSafe",
|
||||
set_setting=False, add_to_group=True, is_active=True)
|
||||
cls.user1 = UserManager.create_user(
|
||||
"user1",
|
||||
"user1@envipath.com",
|
||||
"SuperSafe",
|
||||
set_setting=False,
|
||||
add_to_group=True,
|
||||
is_active=True,
|
||||
)
|
||||
cls.user1_default_package = cls.user1.default_package
|
||||
cls.package = PackageManager.create_package(cls.user1, 'Test', 'Test Pack')
|
||||
cls.package = PackageManager.create_package(cls.user1, "Test", "Test Pack")
|
||||
|
||||
def setUp(self):
|
||||
self.client.force_login(self.user1)
|
||||
|
||||
def test_create_compound(self):
|
||||
response = self.client.post(
|
||||
reverse("compounds"), {
|
||||
reverse("compounds"),
|
||||
{
|
||||
"compound-name": "1,2-Dichloroethane",
|
||||
"compound-description": "Eawag BBD compound c0001",
|
||||
"compound-smiles": "C(CCl)Cl",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
@ -38,17 +45,18 @@ class CompoundViewTest(TestCase):
|
||||
self.assertEqual(c.name, "1,2-Dichloroethane")
|
||||
self.assertEqual(c.description, "Eawag BBD compound c0001")
|
||||
self.assertEqual(c.default_structure.smiles, "C(CCl)Cl")
|
||||
self.assertEqual(c.default_structure.canonical_smiles, 'ClCCCl')
|
||||
self.assertEqual(c.default_structure.canonical_smiles, "ClCCCl")
|
||||
self.assertEqual(c.structures.all().count(), 2)
|
||||
self.assertEqual(self.user1_default_package.compounds.count(), 1)
|
||||
|
||||
# Adding the same rule again should return the existing one, hence not increasing the number of rules
|
||||
response = self.client.post(
|
||||
reverse("compounds"), {
|
||||
reverse("compounds"),
|
||||
{
|
||||
"compound-name": "1,2-Dichloroethane",
|
||||
"compound-description": "Eawag BBD compound c0001",
|
||||
"compound-smiles": "C(CCl)Cl",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.url, compound_url)
|
||||
@ -57,11 +65,12 @@ class CompoundViewTest(TestCase):
|
||||
|
||||
# Adding the same rule in a different package should create a new rule
|
||||
response = self.client.post(
|
||||
reverse("package compound list", kwargs={'package_uuid': self.package.uuid}), {
|
||||
reverse("package compound list", kwargs={"package_uuid": self.package.uuid}),
|
||||
{
|
||||
"compound-name": "1,2-Dichloroethane",
|
||||
"compound-description": "Eawag BBD compound c0001",
|
||||
"compound-smiles": "C(CCl)Cl",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
@ -69,11 +78,12 @@ class CompoundViewTest(TestCase):
|
||||
|
||||
# adding another reaction should increase count
|
||||
response = self.client.post(
|
||||
reverse("compounds"), {
|
||||
reverse("compounds"),
|
||||
{
|
||||
"compound-name": "2-Chloroethanol",
|
||||
"compound-description": "Eawag BBD compound c0005",
|
||||
"compound-smiles": "C(CO)Cl",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
@ -82,11 +92,12 @@ class CompoundViewTest(TestCase):
|
||||
# Edit
|
||||
def test_edit_rule(self):
|
||||
response = self.client.post(
|
||||
reverse("compounds"), {
|
||||
reverse("compounds"),
|
||||
{
|
||||
"compound-name": "1,2-Dichloroethane",
|
||||
"compound-description": "Eawag BBD compound c0001",
|
||||
"compound-smiles": "C(CCl)Cl",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
@ -95,13 +106,17 @@ class CompoundViewTest(TestCase):
|
||||
c = Compound.objects.get(url=compound_url)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("package compound detail", kwargs={
|
||||
'package_uuid': str(self.user1_default_package.uuid),
|
||||
'compound_uuid': str(c.uuid)
|
||||
}), {
|
||||
reverse(
|
||||
"package compound detail",
|
||||
kwargs={
|
||||
"package_uuid": str(self.user1_default_package.uuid),
|
||||
"compound_uuid": str(c.uuid),
|
||||
},
|
||||
),
|
||||
{
|
||||
"compound-name": "Test Compound Adjusted",
|
||||
"compound-description": "New Description",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
@ -121,7 +136,7 @@ class CompoundViewTest(TestCase):
|
||||
"Test Desc",
|
||||
"2025-10",
|
||||
"soil",
|
||||
[Temperature(interval=Interval(start=20, end=30))]
|
||||
[Temperature(interval=Interval(start=20, end=30))],
|
||||
)
|
||||
|
||||
s2 = Scenario.create(
|
||||
@ -130,15 +145,16 @@ class CompoundViewTest(TestCase):
|
||||
"Test Desc2",
|
||||
"2025-10",
|
||||
"soil",
|
||||
[Temperature(interval=Interval(start=10, end=20))]
|
||||
[Temperature(interval=Interval(start=10, end=20))],
|
||||
)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("compounds"), {
|
||||
reverse("compounds"),
|
||||
{
|
||||
"compound-name": "1,2-Dichloroethane",
|
||||
"compound-description": "Eawag BBD compound c0001",
|
||||
"compound-smiles": "C(CCl)Cl",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
@ -147,36 +163,35 @@ class CompoundViewTest(TestCase):
|
||||
c = Compound.objects.get(url=compound_url)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("package compound detail", kwargs={
|
||||
'package_uuid': str(c.package.uuid),
|
||||
'compound_uuid': str(c.uuid)
|
||||
}), {
|
||||
"selected-scenarios": [s1.url, s2.url]
|
||||
}
|
||||
reverse(
|
||||
"package compound detail",
|
||||
kwargs={"package_uuid": str(c.package.uuid), "compound_uuid": str(c.uuid)},
|
||||
),
|
||||
{"selected-scenarios": [s1.url, s2.url]},
|
||||
)
|
||||
|
||||
self.assertEqual(len(c.scenarios.all()), 2)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("package compound detail", kwargs={
|
||||
'package_uuid': str(c.package.uuid),
|
||||
'compound_uuid': str(c.uuid)
|
||||
}), {
|
||||
"selected-scenarios": [s1.url]
|
||||
}
|
||||
reverse(
|
||||
"package compound detail",
|
||||
kwargs={"package_uuid": str(c.package.uuid), "compound_uuid": str(c.uuid)},
|
||||
),
|
||||
{"selected-scenarios": [s1.url]},
|
||||
)
|
||||
|
||||
self.assertEqual(len(c.scenarios.all()), 1)
|
||||
self.assertEqual(c.scenarios.first().url, s1.url)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("package compound detail", kwargs={
|
||||
'package_uuid': str(c.package.uuid),
|
||||
'compound_uuid': str(c.uuid)
|
||||
}), {
|
||||
reverse(
|
||||
"package compound detail",
|
||||
kwargs={"package_uuid": str(c.package.uuid), "compound_uuid": str(c.uuid)},
|
||||
),
|
||||
{
|
||||
# We have to set an empty string to avoid that the parameter is removed
|
||||
"selected-scenarios": ""
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(len(c.scenarios.all()), 0)
|
||||
@ -184,11 +199,12 @@ class CompoundViewTest(TestCase):
|
||||
#
|
||||
def test_copy(self):
|
||||
response = self.client.post(
|
||||
reverse("compounds"), {
|
||||
reverse("compounds"),
|
||||
{
|
||||
"compound-name": "1,2-Dichloroethane",
|
||||
"compound-description": "Eawag BBD compound c0001",
|
||||
"compound-smiles": "C(CCl)Cl",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
@ -196,12 +212,13 @@ class CompoundViewTest(TestCase):
|
||||
c = Compound.objects.get(url=compound_url)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("package detail", kwargs={
|
||||
'package_uuid': str(self.package.uuid),
|
||||
}), {
|
||||
"hidden": "copy",
|
||||
"object_to_copy": c.url
|
||||
}
|
||||
reverse(
|
||||
"package detail",
|
||||
kwargs={
|
||||
"package_uuid": str(self.package.uuid),
|
||||
},
|
||||
),
|
||||
{"hidden": "copy", "object_to_copy": c.url},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
@ -215,44 +232,48 @@ class CompoundViewTest(TestCase):
|
||||
|
||||
# Copy to the same package should fail
|
||||
response = self.client.post(
|
||||
reverse("package detail", kwargs={
|
||||
'package_uuid': str(c.package.uuid),
|
||||
}), {
|
||||
"hidden": "copy",
|
||||
"object_to_copy": c.url
|
||||
}
|
||||
reverse(
|
||||
"package detail",
|
||||
kwargs={
|
||||
"package_uuid": str(c.package.uuid),
|
||||
},
|
||||
),
|
||||
{"hidden": "copy", "object_to_copy": c.url},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertEqual(response.json()['error'], f"Can't copy object {compound_url} to the same package!")
|
||||
self.assertEqual(
|
||||
response.json()["error"], f"Can't copy object {compound_url} to the same package!"
|
||||
)
|
||||
|
||||
def test_references(self):
|
||||
ext_db, _ = ExternalDatabase.objects.get_or_create(
|
||||
name='PubChem Compound',
|
||||
name="PubChem Compound",
|
||||
defaults={
|
||||
'full_name': 'PubChem Compound Database',
|
||||
'description': 'Chemical database of small organic molecules',
|
||||
'base_url': 'https://pubchem.ncbi.nlm.nih.gov',
|
||||
'url_pattern': 'https://pubchem.ncbi.nlm.nih.gov/compound/{id}'
|
||||
}
|
||||
"full_name": "PubChem Compound Database",
|
||||
"description": "Chemical database of small organic molecules",
|
||||
"base_url": "https://pubchem.ncbi.nlm.nih.gov",
|
||||
"url_pattern": "https://pubchem.ncbi.nlm.nih.gov/compound/{id}",
|
||||
},
|
||||
)
|
||||
|
||||
ext_db2, _ = ExternalDatabase.objects.get_or_create(
|
||||
name='PubChem Substance',
|
||||
name="PubChem Substance",
|
||||
defaults={
|
||||
'full_name': 'PubChem Substance Database',
|
||||
'description': 'Database of chemical substances',
|
||||
'base_url': 'https://pubchem.ncbi.nlm.nih.gov',
|
||||
'url_pattern': 'https://pubchem.ncbi.nlm.nih.gov/substance/{id}'
|
||||
}
|
||||
"full_name": "PubChem Substance Database",
|
||||
"description": "Database of chemical substances",
|
||||
"base_url": "https://pubchem.ncbi.nlm.nih.gov",
|
||||
"url_pattern": "https://pubchem.ncbi.nlm.nih.gov/substance/{id}",
|
||||
},
|
||||
)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("compounds"), {
|
||||
reverse("compounds"),
|
||||
{
|
||||
"compound-name": "1,2-Dichloroethane",
|
||||
"compound-description": "Eawag BBD compound c0001",
|
||||
"compound-smiles": "C(CCl)Cl",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
@ -260,42 +281,49 @@ class CompoundViewTest(TestCase):
|
||||
c = Compound.objects.get(url=compound_url)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("package compound detail", kwargs={
|
||||
'package_uuid': str(c.package.uuid),
|
||||
'compound_uuid': str(c.uuid),
|
||||
}), {
|
||||
'selected-database': ext_db.pk,
|
||||
'identifier': '25154249'
|
||||
}
|
||||
reverse(
|
||||
"package compound detail",
|
||||
kwargs={
|
||||
"package_uuid": str(c.package.uuid),
|
||||
"compound_uuid": str(c.uuid),
|
||||
},
|
||||
),
|
||||
{"selected-database": ext_db.pk, "identifier": "25154249"},
|
||||
)
|
||||
|
||||
self.assertEqual(c.external_identifiers.count(), 1)
|
||||
self.assertEqual(c.external_identifiers.first().database, ext_db)
|
||||
self.assertEqual(c.external_identifiers.first().identifier_value, '25154249')
|
||||
self.assertEqual(c.external_identifiers.first().url, 'https://pubchem.ncbi.nlm.nih.gov/compound/25154249')
|
||||
self.assertEqual(c.external_identifiers.first().identifier_value, "25154249")
|
||||
self.assertEqual(
|
||||
c.external_identifiers.first().url, "https://pubchem.ncbi.nlm.nih.gov/compound/25154249"
|
||||
)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("package compound detail", kwargs={
|
||||
'package_uuid': str(c.package.uuid),
|
||||
'compound_uuid': str(c.uuid),
|
||||
}), {
|
||||
'selected-database': ext_db2.pk,
|
||||
'identifier': '25154249'
|
||||
}
|
||||
reverse(
|
||||
"package compound detail",
|
||||
kwargs={
|
||||
"package_uuid": str(c.package.uuid),
|
||||
"compound_uuid": str(c.uuid),
|
||||
},
|
||||
),
|
||||
{"selected-database": ext_db2.pk, "identifier": "25154249"},
|
||||
)
|
||||
|
||||
self.assertEqual(c.external_identifiers.count(), 2)
|
||||
self.assertEqual(c.external_identifiers.last().database, ext_db2)
|
||||
self.assertEqual(c.external_identifiers.last().identifier_value, '25154249')
|
||||
self.assertEqual(c.external_identifiers.last().url, 'https://pubchem.ncbi.nlm.nih.gov/substance/25154249')
|
||||
self.assertEqual(c.external_identifiers.last().identifier_value, "25154249")
|
||||
self.assertEqual(
|
||||
c.external_identifiers.last().url, "https://pubchem.ncbi.nlm.nih.gov/substance/25154249"
|
||||
)
|
||||
|
||||
def test_delete(self):
|
||||
response = self.client.post(
|
||||
reverse("compounds"), {
|
||||
reverse("compounds"),
|
||||
{
|
||||
"compound-name": "1,2-Dichloroethane",
|
||||
"compound-description": "Eawag BBD compound c0001",
|
||||
"compound-smiles": "C(CCl)Cl",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
@ -304,12 +332,11 @@ class CompoundViewTest(TestCase):
|
||||
c = Compound.objects.get(url=compound_url)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("package compound detail", kwargs={
|
||||
'package_uuid': str(c.package.uuid),
|
||||
'compound_uuid': str(c.uuid)
|
||||
}), {
|
||||
"hidden": "delete"
|
||||
}
|
||||
reverse(
|
||||
"package compound detail",
|
||||
kwargs={"package_uuid": str(c.package.uuid), "compound_uuid": str(c.uuid)},
|
||||
),
|
||||
{"hidden": "delete"},
|
||||
)
|
||||
|
||||
self.assertEqual(self.user1_default_package.compounds.count(), 0)
|
||||
|
||||
@ -2,8 +2,8 @@ from django.test import TestCase, override_settings
|
||||
from django.urls import reverse
|
||||
from django.conf import settings as s
|
||||
|
||||
from epdb.logic import UserManager, PackageManager
|
||||
from epdb.models import Pathway, Edge, Package, User
|
||||
from epdb.logic import UserManager
|
||||
from epdb.models import Package, User
|
||||
|
||||
|
||||
@override_settings(MODEL_DIR=s.FIXTURE_DIRS[0] / "models")
|
||||
@ -13,10 +13,16 @@ class PathwayViewTest(TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(PathwayViewTest, cls).setUpClass()
|
||||
cls.user1 = UserManager.create_user("user1", "user1@envipath.com", "SuperSafe",
|
||||
set_setting=True, add_to_group=True, is_active=True)
|
||||
cls.user1 = UserManager.create_user(
|
||||
"user1",
|
||||
"user1@envipath.com",
|
||||
"SuperSafe",
|
||||
set_setting=True,
|
||||
add_to_group=True,
|
||||
is_active=True,
|
||||
)
|
||||
cls.user1_default_package = cls.user1.default_package
|
||||
cls.model_package = Package.objects.get(name='Fixtures')
|
||||
cls.model_package = Package.objects.get(name="Fixtures")
|
||||
|
||||
def setUp(self):
|
||||
self.client.force_login(self.user1)
|
||||
@ -24,90 +30,96 @@ class PathwayViewTest(TestCase):
|
||||
def test_predict(self):
|
||||
self.client.force_login(User.objects.get(username="admin"))
|
||||
response = self.client.get(
|
||||
reverse("package model detail", kwargs={
|
||||
'package_uuid': str(self.model_package.uuid),
|
||||
'model_uuid': str(self.model_package.models.first().uuid)
|
||||
}), {
|
||||
'classify': 'ILikeCats!',
|
||||
'smiles': 'CCN(CC)C(=O)C1=CC(=CC=C1)CO',
|
||||
}
|
||||
reverse(
|
||||
"package model detail",
|
||||
kwargs={
|
||||
"package_uuid": str(self.model_package.uuid),
|
||||
"model_uuid": str(self.model_package.models.first().uuid),
|
||||
},
|
||||
),
|
||||
{
|
||||
"classify": "ILikeCats!",
|
||||
"smiles": "CCN(CC)C(=O)C1=CC(=CC=C1)CO",
|
||||
},
|
||||
)
|
||||
|
||||
expected = [
|
||||
{
|
||||
'products': [
|
||||
[
|
||||
'O=C(O)C1=CC(CO)=CC=C1',
|
||||
'CCNCC'
|
||||
]
|
||||
],
|
||||
'probability': 0.25,
|
||||
'btrule': {
|
||||
'url': 'http://localhost:8000/package/1869d3f0-60bb-41fd-b6f8-afa75ffb09d3/simple-ambit-rule/0e6e9290-b658-4450-b291-3ec19fa19206',
|
||||
'name': 'bt0430-4011'
|
||||
}
|
||||
}, {
|
||||
'products': [
|
||||
[
|
||||
'CCNC(=O)C1=CC(CO)=CC=C1',
|
||||
'CC=O'
|
||||
]
|
||||
], 'probability': 0.0,
|
||||
'btrule': {
|
||||
'url': 'http://localhost:8000/package/1869d3f0-60bb-41fd-b6f8-afa75ffb09d3/simple-ambit-rule/27a3a353-0b66-4228-bd16-e407949e90df',
|
||||
'name': 'bt0243-4301'
|
||||
}
|
||||
}, {
|
||||
'products': [
|
||||
[
|
||||
'CCN(CC)C(=O)C1=CC(C=O)=CC=C1'
|
||||
]
|
||||
], 'probability': 0.75,
|
||||
'btrule': {
|
||||
'url': 'http://localhost:8000/package/1869d3f0-60bb-41fd-b6f8-afa75ffb09d3/simple-ambit-rule/2f2e0c39-e109-4836-959f-2bda2524f022',
|
||||
'name': 'bt0001-3568'
|
||||
}
|
||||
}
|
||||
"products": [["O=C(O)C1=CC(CO)=CC=C1", "CCNCC"]],
|
||||
"probability": 0.25,
|
||||
"btrule": {
|
||||
"url": "http://localhost:8000/package/1869d3f0-60bb-41fd-b6f8-afa75ffb09d3/simple-ambit-rule/0e6e9290-b658-4450-b291-3ec19fa19206",
|
||||
"name": "bt0430-4011",
|
||||
},
|
||||
},
|
||||
{
|
||||
"products": [["CCNC(=O)C1=CC(CO)=CC=C1", "CC=O"]],
|
||||
"probability": 0.0,
|
||||
"btrule": {
|
||||
"url": "http://localhost:8000/package/1869d3f0-60bb-41fd-b6f8-afa75ffb09d3/simple-ambit-rule/27a3a353-0b66-4228-bd16-e407949e90df",
|
||||
"name": "bt0243-4301",
|
||||
},
|
||||
},
|
||||
{
|
||||
"products": [["CCN(CC)C(=O)C1=CC(C=O)=CC=C1"]],
|
||||
"probability": 0.75,
|
||||
"btrule": {
|
||||
"url": "http://localhost:8000/package/1869d3f0-60bb-41fd-b6f8-afa75ffb09d3/simple-ambit-rule/2f2e0c39-e109-4836-959f-2bda2524f022",
|
||||
"name": "bt0001-3568",
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
actual = response.json()
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
response = self.client.get(
|
||||
reverse("package model detail", kwargs={
|
||||
'package_uuid': str(self.model_package.uuid),
|
||||
'model_uuid': str(self.model_package.models.first().uuid)
|
||||
}), {
|
||||
'classify': 'ILikeCats!',
|
||||
'smiles': '',
|
||||
}
|
||||
reverse(
|
||||
"package model detail",
|
||||
kwargs={
|
||||
"package_uuid": str(self.model_package.uuid),
|
||||
"model_uuid": str(self.model_package.models.first().uuid),
|
||||
},
|
||||
),
|
||||
{
|
||||
"classify": "ILikeCats!",
|
||||
"smiles": "",
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertEqual(response.json()['error'], 'Received empty SMILES')
|
||||
self.assertEqual(response.json()["error"], "Received empty SMILES")
|
||||
|
||||
response = self.client.get(
|
||||
reverse("package model detail", kwargs={
|
||||
'package_uuid': str(self.model_package.uuid),
|
||||
'model_uuid': str(self.model_package.models.first().uuid)
|
||||
}), {
|
||||
'classify': 'ILikeCats!',
|
||||
'smiles': ' ', # Input should be stripped
|
||||
}
|
||||
reverse(
|
||||
"package model detail",
|
||||
kwargs={
|
||||
"package_uuid": str(self.model_package.uuid),
|
||||
"model_uuid": str(self.model_package.models.first().uuid),
|
||||
},
|
||||
),
|
||||
{
|
||||
"classify": "ILikeCats!",
|
||||
"smiles": " ", # Input should be stripped
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertEqual(response.json()['error'], 'Received empty SMILES')
|
||||
self.assertEqual(response.json()["error"], "Received empty SMILES")
|
||||
|
||||
response = self.client.get(
|
||||
reverse("package model detail", kwargs={
|
||||
'package_uuid': str(self.model_package.uuid),
|
||||
'model_uuid': str(self.model_package.models.first().uuid)
|
||||
}), {
|
||||
'classify': 'ILikeCats!',
|
||||
'smiles': 'RandomInput',
|
||||
}
|
||||
reverse(
|
||||
"package model detail",
|
||||
kwargs={
|
||||
"package_uuid": str(self.model_package.uuid),
|
||||
"model_uuid": str(self.model_package.models.first().uuid),
|
||||
},
|
||||
),
|
||||
{
|
||||
"classify": "ILikeCats!",
|
||||
"smiles": "RandomInput",
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertEqual(response.json()['error'], '"RandomInput" is not a valid SMILES')
|
||||
self.assertEqual(response.json()["error"], '"RandomInput" is not a valid SMILES')
|
||||
|
||||
@ -13,19 +13,34 @@ class PackageViewTest(TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(PackageViewTest, cls).setUpClass()
|
||||
cls.user1 = UserManager.create_user("user1", "user1@envipath.com", "SuperSafe",
|
||||
set_setting=False, add_to_group=True, is_active=True)
|
||||
cls.user2 = UserManager.create_user("user2", "user2@envipath.com", "SuperSafe",
|
||||
set_setting=False, add_to_group=True, is_active=True)
|
||||
cls.user1 = UserManager.create_user(
|
||||
"user1",
|
||||
"user1@envipath.com",
|
||||
"SuperSafe",
|
||||
set_setting=False,
|
||||
add_to_group=True,
|
||||
is_active=True,
|
||||
)
|
||||
cls.user2 = UserManager.create_user(
|
||||
"user2",
|
||||
"user2@envipath.com",
|
||||
"SuperSafe",
|
||||
set_setting=False,
|
||||
add_to_group=True,
|
||||
is_active=True,
|
||||
)
|
||||
|
||||
def setUp(self):
|
||||
self.client.force_login(self.user1)
|
||||
|
||||
def test_create_package(self):
|
||||
response = self.client.post(reverse("packages"), {
|
||||
"package-name": "Test Package",
|
||||
"package-description": "Just a Description",
|
||||
})
|
||||
response = self.client.post(
|
||||
reverse("packages"),
|
||||
{
|
||||
"package-name": "Test Package",
|
||||
"package-description": "Just a Description",
|
||||
},
|
||||
)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
package_url = response.url
|
||||
|
||||
@ -41,13 +56,12 @@ class PackageViewTest(TestCase):
|
||||
file = SimpleUploadedFile(
|
||||
"Fixture_Package.json",
|
||||
open(s.FIXTURE_DIRS[0] / "Fixture_Package.json", "rb").read(),
|
||||
content_type="application/json"
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
response = self.client.post(reverse("packages"), {
|
||||
"file": file,
|
||||
"hidden": "import-package-json"
|
||||
})
|
||||
response = self.client.post(
|
||||
reverse("packages"), {"file": file, "hidden": "import-package-json"}
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
package_url = response.url
|
||||
@ -67,13 +81,12 @@ class PackageViewTest(TestCase):
|
||||
file = SimpleUploadedFile(
|
||||
"EAWAG-BBD.json",
|
||||
open(s.FIXTURE_DIRS[0] / "packages" / "2025-07-18" / "EAWAG-BBD.json", "rb").read(),
|
||||
content_type="application/json"
|
||||
content_type="application/json",
|
||||
)
|
||||
|
||||
response = self.client.post(reverse("packages"), {
|
||||
"file": file,
|
||||
"hidden": "import-legacy-package-json"
|
||||
})
|
||||
response = self.client.post(
|
||||
reverse("packages"), {"file": file, "hidden": "import-legacy-package-json"}
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
package_url = response.url
|
||||
@ -90,17 +103,23 @@ class PackageViewTest(TestCase):
|
||||
self.assertEqual(upp.permission, Permission.ALL[0])
|
||||
|
||||
def test_edit_package(self):
|
||||
response = self.client.post(reverse("packages"), {
|
||||
"package-name": "Test Package",
|
||||
"package-description": "Just a Description",
|
||||
})
|
||||
response = self.client.post(
|
||||
reverse("packages"),
|
||||
{
|
||||
"package-name": "Test Package",
|
||||
"package-description": "Just a Description",
|
||||
},
|
||||
)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
package_url = response.url
|
||||
|
||||
self.client.post(package_url, {
|
||||
"package-name": "New Name",
|
||||
"package-description": "New Description",
|
||||
})
|
||||
self.client.post(
|
||||
package_url,
|
||||
{
|
||||
"package-name": "New Name",
|
||||
"package-description": "New Description",
|
||||
},
|
||||
)
|
||||
|
||||
p = Package.objects.get(url=package_url)
|
||||
|
||||
@ -108,10 +127,13 @@ class PackageViewTest(TestCase):
|
||||
self.assertEqual(p.description, "New Description")
|
||||
|
||||
def test_edit_package_permissions(self):
|
||||
response = self.client.post(reverse("packages"), {
|
||||
"package-name": "Test Package",
|
||||
"package-description": "Just a Description",
|
||||
})
|
||||
response = self.client.post(
|
||||
reverse("packages"),
|
||||
{
|
||||
"package-name": "Test Package",
|
||||
"package-description": "Just a Description",
|
||||
},
|
||||
)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
package_url = response.url
|
||||
p = Package.objects.get(url=package_url)
|
||||
@ -119,57 +141,63 @@ class PackageViewTest(TestCase):
|
||||
with self.assertRaises(UserPackagePermission.DoesNotExist):
|
||||
UserPackagePermission.objects.get(package=p, user=self.user2)
|
||||
|
||||
self.client.post(package_url, {
|
||||
"grantee": self.user2.url,
|
||||
"read": "on",
|
||||
"write": "on",
|
||||
})
|
||||
self.client.post(
|
||||
package_url,
|
||||
{
|
||||
"grantee": self.user2.url,
|
||||
"read": "on",
|
||||
"write": "on",
|
||||
},
|
||||
)
|
||||
|
||||
upp = UserPackagePermission.objects.get(package=p, user=self.user2)
|
||||
|
||||
self.assertEqual(upp.permission, Permission.WRITE[0])
|
||||
|
||||
def test_publish_package(self):
|
||||
response = self.client.post(reverse("packages"), {
|
||||
"package-name": "Test Package",
|
||||
"package-description": "Just a Description",
|
||||
})
|
||||
response = self.client.post(
|
||||
reverse("packages"),
|
||||
{
|
||||
"package-name": "Test Package",
|
||||
"package-description": "Just a Description",
|
||||
},
|
||||
)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
package_url = response.url
|
||||
p = Package.objects.get(url=package_url)
|
||||
|
||||
self.client.post(package_url, {
|
||||
"hidden": "publish-package"
|
||||
})
|
||||
self.client.post(package_url, {"hidden": "publish-package"})
|
||||
|
||||
self.assertEqual(Group.objects.filter(public=True).count(), 1)
|
||||
g = Group.objects.get(public=True)
|
||||
gpp = GroupPackagePermission.objects.get(package=p, group=g)
|
||||
self.assertEqual(gpp.permission, Permission.READ[0])
|
||||
|
||||
|
||||
def test_set_package_license(self):
|
||||
response = self.client.post(reverse("packages"), {
|
||||
"package-name": "Test Package",
|
||||
"package-description": "Just a Description",
|
||||
})
|
||||
response = self.client.post(
|
||||
reverse("packages"),
|
||||
{
|
||||
"package-name": "Test Package",
|
||||
"package-description": "Just a Description",
|
||||
},
|
||||
)
|
||||
|
||||
package_url = response.url
|
||||
p = Package.objects.get(url=package_url)
|
||||
|
||||
self.client.post(package_url, {
|
||||
"license": "no-license"
|
||||
})
|
||||
self.client.post(package_url, {"license": "no-license"})
|
||||
|
||||
self.assertIsNone(p.license)
|
||||
# TODO test others
|
||||
|
||||
|
||||
def test_delete_package(self):
|
||||
response = self.client.post(reverse("packages"), {
|
||||
"package-name": "Test Package",
|
||||
"package-description": "Just a Description",
|
||||
})
|
||||
response = self.client.post(
|
||||
reverse("packages"),
|
||||
{
|
||||
"package-name": "Test Package",
|
||||
"package-description": "Just a Description",
|
||||
},
|
||||
)
|
||||
|
||||
package_url = response.url
|
||||
p = Package.objects.get(url=package_url)
|
||||
@ -182,11 +210,11 @@ class PackageViewTest(TestCase):
|
||||
def test_delete_default_package(self):
|
||||
self.client.force_login(self.user1)
|
||||
# Try to delete the default package
|
||||
response = self.client.post(self.user1.default_package.url, {
|
||||
"hidden": "delete"
|
||||
})
|
||||
response = self.client.post(self.user1.default_package.url, {"hidden": "delete"})
|
||||
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertTrue(f'You cannot delete the default package. '
|
||||
f'If you want to delete this package you have to '
|
||||
f'set another default package first' in response.content.decode())
|
||||
self.assertTrue(
|
||||
"You cannot delete the default package. "
|
||||
"If you want to delete this package you have to "
|
||||
"set another default package first" in response.content.decode()
|
||||
)
|
||||
|
||||
@ -5,6 +5,7 @@ from django.conf import settings as s
|
||||
from epdb.logic import UserManager, PackageManager
|
||||
from epdb.models import Pathway, Edge
|
||||
|
||||
|
||||
@override_settings(MODEL_DIR=s.FIXTURE_DIRS[0] / "models")
|
||||
class PathwayViewTest(TestCase):
|
||||
fixtures = ["test_fixtures_incl_model.jsonl.gz"]
|
||||
@ -12,41 +13,52 @@ class PathwayViewTest(TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(PathwayViewTest, cls).setUpClass()
|
||||
cls.user1 = UserManager.create_user("user1", "user1@envipath.com", "SuperSafe",
|
||||
set_setting=True, add_to_group=True, is_active=True)
|
||||
cls.user1 = UserManager.create_user(
|
||||
"user1",
|
||||
"user1@envipath.com",
|
||||
"SuperSafe",
|
||||
set_setting=True,
|
||||
add_to_group=True,
|
||||
is_active=True,
|
||||
)
|
||||
cls.user1_default_package = cls.user1.default_package
|
||||
cls.package = PackageManager.create_package(cls.user1, 'Test', 'Test Pack')
|
||||
cls.package = PackageManager.create_package(cls.user1, "Test", "Test Pack")
|
||||
|
||||
def setUp(self):
|
||||
self.client.force_login(self.user1)
|
||||
|
||||
def test_predict_pathway(self):
|
||||
response = self.client.post(reverse("pathways"), {
|
||||
'name': 'Test Pathway',
|
||||
'description': 'Just a Description',
|
||||
'predict': 'predict',
|
||||
'smiles': 'CCN(CC)C(=O)C1=CC(=CC=C1)CO',
|
||||
})
|
||||
response = self.client.post(
|
||||
reverse("pathways"),
|
||||
{
|
||||
"name": "Test Pathway",
|
||||
"description": "Just a Description",
|
||||
"predict": "predict",
|
||||
"smiles": "CCN(CC)C(=O)C1=CC(=CC=C1)CO",
|
||||
},
|
||||
)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
pathway_url = response.url
|
||||
|
||||
pw = Pathway.objects.get(url=pathway_url)
|
||||
self.assertEqual(self.user1_default_package, pw.package)
|
||||
|
||||
self.assertEqual(pw.name, 'Test Pathway')
|
||||
self.assertEqual(pw.description, 'Just a Description')
|
||||
self.assertEqual(pw.name, "Test Pathway")
|
||||
self.assertEqual(pw.description, "Just a Description")
|
||||
self.assertEqual(len(pw.root_nodes), 1)
|
||||
self.assertEqual(pw.root_nodes.first().default_node_label.smiles, 'CCN(CC)C(=O)C1=CC(CO)=CC=C1')
|
||||
self.assertEqual(
|
||||
pw.root_nodes.first().default_node_label.smiles, "CCN(CC)C(=O)C1=CC(CO)=CC=C1"
|
||||
)
|
||||
|
||||
first_level_nodes = {
|
||||
# Edge 1
|
||||
'CCN(CC)C(=O)C1=CC(C=O)=CC=C1',
|
||||
"CCN(CC)C(=O)C1=CC(C=O)=CC=C1",
|
||||
# Edge 2
|
||||
'CCNC(=O)C1=CC(CO)=CC=C1',
|
||||
'CC=O',
|
||||
"CCNC(=O)C1=CC(CO)=CC=C1",
|
||||
"CC=O",
|
||||
# Edge 3
|
||||
'CCNCC',
|
||||
'O=C(O)C1=CC(CO)=CC=C1',
|
||||
"CCNCC",
|
||||
"O=C(O)C1=CC(CO)=CC=C1",
|
||||
}
|
||||
|
||||
predicted_nodes = set()
|
||||
@ -60,32 +72,36 @@ class PathwayViewTest(TestCase):
|
||||
|
||||
def test_predict_package_pathway(self):
|
||||
response = self.client.post(
|
||||
reverse("package pathway list", kwargs={'package_uuid': str(self.package.uuid)}), {
|
||||
'name': 'Test Pathway',
|
||||
'description': 'Just a Description',
|
||||
'predict': 'predict',
|
||||
'smiles': 'CCN(CC)C(=O)C1=CC(=CC=C1)CO',
|
||||
})
|
||||
reverse("package pathway list", kwargs={"package_uuid": str(self.package.uuid)}),
|
||||
{
|
||||
"name": "Test Pathway",
|
||||
"description": "Just a Description",
|
||||
"predict": "predict",
|
||||
"smiles": "CCN(CC)C(=O)C1=CC(=CC=C1)CO",
|
||||
},
|
||||
)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
pathway_url = response.url
|
||||
|
||||
pw = Pathway.objects.get(url=pathway_url)
|
||||
self.assertEqual(self.package, pw.package)
|
||||
|
||||
self.assertEqual(pw.name, 'Test Pathway')
|
||||
self.assertEqual(pw.description, 'Just a Description')
|
||||
self.assertEqual(pw.name, "Test Pathway")
|
||||
self.assertEqual(pw.description, "Just a Description")
|
||||
self.assertEqual(len(pw.root_nodes), 1)
|
||||
self.assertEqual(pw.root_nodes.first().default_node_label.smiles, 'CCN(CC)C(=O)C1=CC(CO)=CC=C1')
|
||||
self.assertEqual(
|
||||
pw.root_nodes.first().default_node_label.smiles, "CCN(CC)C(=O)C1=CC(CO)=CC=C1"
|
||||
)
|
||||
|
||||
first_level_nodes = {
|
||||
# Edge 1
|
||||
'CCN(CC)C(=O)C1=CC(C=O)=CC=C1',
|
||||
"CCN(CC)C(=O)C1=CC(C=O)=CC=C1",
|
||||
# Edge 2
|
||||
'CCNC(=O)C1=CC(CO)=CC=C1',
|
||||
'CC=O',
|
||||
"CCNC(=O)C1=CC(CO)=CC=C1",
|
||||
"CC=O",
|
||||
# Edge 3
|
||||
'CCNCC',
|
||||
'O=C(O)C1=CC(CO)=CC=C1',
|
||||
"CCNCC",
|
||||
"O=C(O)C1=CC(CO)=CC=C1",
|
||||
}
|
||||
|
||||
predicted_nodes = set()
|
||||
|
||||
@ -3,7 +3,7 @@ from django.urls import reverse
|
||||
from envipy_additional_information import Temperature, Interval
|
||||
|
||||
from epdb.logic import UserManager, PackageManager
|
||||
from epdb.models import Reaction, Scenario, ExternalIdentifier, ExternalDatabase
|
||||
from epdb.models import Reaction, Scenario, ExternalDatabase
|
||||
|
||||
|
||||
class ReactionViewTest(TestCase):
|
||||
@ -12,21 +12,28 @@ class ReactionViewTest(TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(ReactionViewTest, cls).setUpClass()
|
||||
cls.user1 = UserManager.create_user("user1", "user1@envipath.com", "SuperSafe",
|
||||
set_setting=False, add_to_group=True, is_active=True)
|
||||
cls.user1 = UserManager.create_user(
|
||||
"user1",
|
||||
"user1@envipath.com",
|
||||
"SuperSafe",
|
||||
set_setting=False,
|
||||
add_to_group=True,
|
||||
is_active=True,
|
||||
)
|
||||
cls.user1_default_package = cls.user1.default_package
|
||||
cls.package = PackageManager.create_package(cls.user1, 'Test', 'Test Pack')
|
||||
cls.package = PackageManager.create_package(cls.user1, "Test", "Test Pack")
|
||||
|
||||
def setUp(self):
|
||||
self.client.force_login(self.user1)
|
||||
|
||||
def test_create_reaction(self):
|
||||
response = self.client.post(
|
||||
reverse("reactions"), {
|
||||
reverse("reactions"),
|
||||
{
|
||||
"reaction-name": "Eawag BBD reaction r0001",
|
||||
"reaction-description": "Description for Eawag BBD reaction r0001",
|
||||
"reaction-smirks": "C(CCl)Cl>>C(CO)Cl",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
@ -42,11 +49,12 @@ class ReactionViewTest(TestCase):
|
||||
|
||||
# Adding the same rule again should return the existing one, hence not increasing the number of rules
|
||||
response = self.client.post(
|
||||
reverse("reactions"), {
|
||||
reverse("reactions"),
|
||||
{
|
||||
"reaction-name": "Eawag BBD reaction r0001",
|
||||
"reaction-description": "Description for Eawag BBD reaction r0001",
|
||||
"reaction-smirks": "C(CCl)Cl>>C(CO)Cl",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.url, reaction_url)
|
||||
@ -55,11 +63,12 @@ class ReactionViewTest(TestCase):
|
||||
|
||||
# Adding the same rule in a different package should create a new rule
|
||||
response = self.client.post(
|
||||
reverse("package reaction list", kwargs={'package_uuid': self.package.uuid}), {
|
||||
reverse("package reaction list", kwargs={"package_uuid": self.package.uuid}),
|
||||
{
|
||||
"reaction-name": "Eawag BBD reaction r0001",
|
||||
"reaction-description": "Description for Eawag BBD reaction r0001",
|
||||
"reaction-smirks": "C(CCl)Cl>>C(CO)Cl",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
@ -67,11 +76,12 @@ class ReactionViewTest(TestCase):
|
||||
|
||||
# adding another reaction should increase count
|
||||
response = self.client.post(
|
||||
reverse("reactions"), {
|
||||
reverse("reactions"),
|
||||
{
|
||||
"reaction-name": "Eawag BBD reaction r0002",
|
||||
"reaction-description": "Description for Eawag BBD reaction r0002",
|
||||
"reaction-smirks": "C(CO)Cl>>C(C=O)Cl",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
@ -80,11 +90,12 @@ class ReactionViewTest(TestCase):
|
||||
# Edit
|
||||
def test_edit_rule(self):
|
||||
response = self.client.post(
|
||||
reverse("reactions"), {
|
||||
reverse("reactions"),
|
||||
{
|
||||
"reaction-name": "Eawag BBD reaction r0001",
|
||||
"reaction-description": "Description for Eawag BBD reaction r0001",
|
||||
"reaction-smirks": "C(CCl)Cl>>C(CO)Cl",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
@ -93,13 +104,17 @@ class ReactionViewTest(TestCase):
|
||||
r = Reaction.objects.get(url=reaction_url)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("package reaction detail", kwargs={
|
||||
'package_uuid': str(self.user1_default_package.uuid),
|
||||
'reaction_uuid': str(r.uuid)
|
||||
}), {
|
||||
reverse(
|
||||
"package reaction detail",
|
||||
kwargs={
|
||||
"package_uuid": str(self.user1_default_package.uuid),
|
||||
"reaction_uuid": str(r.uuid),
|
||||
},
|
||||
),
|
||||
{
|
||||
"reaction-name": "Test Reaction Adjusted",
|
||||
"reaction-description": "New Description",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
@ -119,7 +134,7 @@ class ReactionViewTest(TestCase):
|
||||
"Test Desc",
|
||||
"2025-10",
|
||||
"soil",
|
||||
[Temperature(interval=Interval(start=20, end=30))]
|
||||
[Temperature(interval=Interval(start=20, end=30))],
|
||||
)
|
||||
|
||||
s2 = Scenario.create(
|
||||
@ -128,15 +143,16 @@ class ReactionViewTest(TestCase):
|
||||
"Test Desc2",
|
||||
"2025-10",
|
||||
"soil",
|
||||
[Temperature(interval=Interval(start=10, end=20))]
|
||||
[Temperature(interval=Interval(start=10, end=20))],
|
||||
)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("reactions"), {
|
||||
reverse("reactions"),
|
||||
{
|
||||
"reaction-name": "Eawag BBD reaction r0001",
|
||||
"reaction-description": "Description for Eawag BBD reaction r0001",
|
||||
"reaction-smirks": "C(CCl)Cl>>C(CO)Cl",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
@ -144,47 +160,47 @@ class ReactionViewTest(TestCase):
|
||||
r = Reaction.objects.get(url=reaction_url)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("package reaction detail", kwargs={
|
||||
'package_uuid': str(r.package.uuid),
|
||||
'reaction_uuid': str(r.uuid)
|
||||
}), {
|
||||
"selected-scenarios": [s1.url, s2.url]
|
||||
}
|
||||
reverse(
|
||||
"package reaction detail",
|
||||
kwargs={"package_uuid": str(r.package.uuid), "reaction_uuid": str(r.uuid)},
|
||||
),
|
||||
{"selected-scenarios": [s1.url, s2.url]},
|
||||
)
|
||||
|
||||
self.assertEqual(len(r.scenarios.all()), 2)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("package reaction detail", kwargs={
|
||||
'package_uuid': str(r.package.uuid),
|
||||
'reaction_uuid': str(r.uuid)
|
||||
}), {
|
||||
"selected-scenarios": [s1.url]
|
||||
}
|
||||
reverse(
|
||||
"package reaction detail",
|
||||
kwargs={"package_uuid": str(r.package.uuid), "reaction_uuid": str(r.uuid)},
|
||||
),
|
||||
{"selected-scenarios": [s1.url]},
|
||||
)
|
||||
|
||||
self.assertEqual(len(r.scenarios.all()), 1)
|
||||
self.assertEqual(r.scenarios.first().url, s1.url)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("package reaction detail", kwargs={
|
||||
'package_uuid': str(r.package.uuid),
|
||||
'reaction_uuid': str(r.uuid)
|
||||
}), {
|
||||
reverse(
|
||||
"package reaction detail",
|
||||
kwargs={"package_uuid": str(r.package.uuid), "reaction_uuid": str(r.uuid)},
|
||||
),
|
||||
{
|
||||
# We have to set an empty string to avoid that the parameter is removed
|
||||
"selected-scenarios": ""
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(len(r.scenarios.all()), 0)
|
||||
|
||||
def test_copy(self):
|
||||
response = self.client.post(
|
||||
reverse("reactions"), {
|
||||
reverse("reactions"),
|
||||
{
|
||||
"reaction-name": "Eawag BBD reaction r0001",
|
||||
"reaction-description": "Description for Eawag BBD reaction r0001",
|
||||
"reaction-smirks": "C(CCl)Cl>>C(CO)Cl",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
@ -192,12 +208,13 @@ class ReactionViewTest(TestCase):
|
||||
r = Reaction.objects.get(url=reaction_url)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("package detail", kwargs={
|
||||
'package_uuid': str(self.package.uuid),
|
||||
}), {
|
||||
"hidden": "copy",
|
||||
"object_to_copy": r.url
|
||||
}
|
||||
reverse(
|
||||
"package detail",
|
||||
kwargs={
|
||||
"package_uuid": str(self.package.uuid),
|
||||
},
|
||||
),
|
||||
{"hidden": "copy", "object_to_copy": r.url},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
@ -211,44 +228,48 @@ class ReactionViewTest(TestCase):
|
||||
|
||||
# Copy to the same package should fail
|
||||
response = self.client.post(
|
||||
reverse("package detail", kwargs={
|
||||
'package_uuid': str(r.package.uuid),
|
||||
}), {
|
||||
"hidden": "copy",
|
||||
"object_to_copy": r.url
|
||||
}
|
||||
reverse(
|
||||
"package detail",
|
||||
kwargs={
|
||||
"package_uuid": str(r.package.uuid),
|
||||
},
|
||||
),
|
||||
{"hidden": "copy", "object_to_copy": r.url},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertEqual(response.json()['error'], f"Can't copy object {reaction_url} to the same package!")
|
||||
self.assertEqual(
|
||||
response.json()["error"], f"Can't copy object {reaction_url} to the same package!"
|
||||
)
|
||||
|
||||
def test_references(self):
|
||||
ext_db, _ = ExternalDatabase.objects.get_or_create(
|
||||
name='KEGG Reaction',
|
||||
name="KEGG Reaction",
|
||||
defaults={
|
||||
'full_name': 'KEGG Reaction Database',
|
||||
'description': 'Database of biochemical reactions',
|
||||
'base_url': 'https://www.genome.jp',
|
||||
'url_pattern': 'https://www.genome.jp/entry/{id}'
|
||||
}
|
||||
"full_name": "KEGG Reaction Database",
|
||||
"description": "Database of biochemical reactions",
|
||||
"base_url": "https://www.genome.jp",
|
||||
"url_pattern": "https://www.genome.jp/entry/{id}",
|
||||
},
|
||||
)
|
||||
|
||||
ext_db2, _ = ExternalDatabase.objects.get_or_create(
|
||||
name='RHEA',
|
||||
name="RHEA",
|
||||
defaults={
|
||||
'full_name': 'RHEA Reaction Database',
|
||||
'description': 'Comprehensive resource of biochemical reactions',
|
||||
'base_url': 'https://www.rhea-db.org',
|
||||
'url_pattern': 'https://www.rhea-db.org/rhea/{id}'
|
||||
"full_name": "RHEA Reaction Database",
|
||||
"description": "Comprehensive resource of biochemical reactions",
|
||||
"base_url": "https://www.rhea-db.org",
|
||||
"url_pattern": "https://www.rhea-db.org/rhea/{id}",
|
||||
},
|
||||
)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("reactions"), {
|
||||
reverse("reactions"),
|
||||
{
|
||||
"reaction-name": "Eawag BBD reaction r0001",
|
||||
"reaction-description": "Description for Eawag BBD reaction r0001",
|
||||
"reaction-smirks": "C(CCl)Cl>>C(CO)Cl",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
@ -256,45 +277,49 @@ class ReactionViewTest(TestCase):
|
||||
r = Reaction.objects.get(url=reaction_url)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("package reaction detail", kwargs={
|
||||
'package_uuid': str(r.package.uuid),
|
||||
'reaction_uuid': str(r.uuid),
|
||||
}), {
|
||||
'selected-database': ext_db.pk,
|
||||
'identifier': 'C12345'
|
||||
}
|
||||
reverse(
|
||||
"package reaction detail",
|
||||
kwargs={
|
||||
"package_uuid": str(r.package.uuid),
|
||||
"reaction_uuid": str(r.uuid),
|
||||
},
|
||||
),
|
||||
{"selected-database": ext_db.pk, "identifier": "C12345"},
|
||||
)
|
||||
|
||||
self.assertEqual(r.external_identifiers.count(), 1)
|
||||
self.assertEqual(r.external_identifiers.first().database, ext_db)
|
||||
self.assertEqual(r.external_identifiers.first().identifier_value, 'C12345')
|
||||
self.assertEqual(r.external_identifiers.first().identifier_value, "C12345")
|
||||
# TODO Fixture contains old url template there the real test fails, use old value instead
|
||||
# self.assertEqual(r.external_identifiers.first().url, 'https://www.genome.jp/entry/C12345')
|
||||
self.assertEqual(r.external_identifiers.first().url, 'https://www.genome.jp/entry/reaction+C12345')
|
||||
self.assertEqual(
|
||||
r.external_identifiers.first().url, "https://www.genome.jp/entry/reaction+C12345"
|
||||
)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("package reaction detail", kwargs={
|
||||
'package_uuid': str(r.package.uuid),
|
||||
'reaction_uuid': str(r.uuid),
|
||||
}), {
|
||||
'selected-database': ext_db2.pk,
|
||||
'identifier': '60116'
|
||||
}
|
||||
reverse(
|
||||
"package reaction detail",
|
||||
kwargs={
|
||||
"package_uuid": str(r.package.uuid),
|
||||
"reaction_uuid": str(r.uuid),
|
||||
},
|
||||
),
|
||||
{"selected-database": ext_db2.pk, "identifier": "60116"},
|
||||
)
|
||||
|
||||
self.assertEqual(r.external_identifiers.count(), 2)
|
||||
self.assertEqual(r.external_identifiers.last().database, ext_db2)
|
||||
self.assertEqual(r.external_identifiers.last().identifier_value, '60116')
|
||||
self.assertEqual(r.external_identifiers.last().url, 'https://www.rhea-db.org/rhea/60116')
|
||||
|
||||
self.assertEqual(r.external_identifiers.last().identifier_value, "60116")
|
||||
self.assertEqual(r.external_identifiers.last().url, "https://www.rhea-db.org/rhea/60116")
|
||||
|
||||
def test_delete(self):
|
||||
response = self.client.post(
|
||||
reverse("reactions"), {
|
||||
reverse("reactions"),
|
||||
{
|
||||
"reaction-name": "Eawag BBD reaction r0001",
|
||||
"reaction-description": "Description for Eawag BBD reaction r0001",
|
||||
"reaction-smirks": "C(CCl)Cl>>C(CO)Cl",
|
||||
}
|
||||
},
|
||||
)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
@ -302,12 +327,11 @@ class ReactionViewTest(TestCase):
|
||||
r = Reaction.objects.get(url=reaction_url)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("package reaction detail", kwargs={
|
||||
'package_uuid': str(r.package.uuid),
|
||||
'reaction_uuid': str(r.uuid)
|
||||
}), {
|
||||
"hidden": "delete"
|
||||
}
|
||||
reverse(
|
||||
"package reaction detail",
|
||||
kwargs={"package_uuid": str(r.package.uuid), "reaction_uuid": str(r.uuid)},
|
||||
),
|
||||
{"hidden": "delete"},
|
||||
)
|
||||
|
||||
self.assertEqual(self.user1_default_package.reactions.count(), 0)
|
||||
|
||||
@ -12,22 +12,29 @@ class RuleViewTest(TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(RuleViewTest, cls).setUpClass()
|
||||
cls.user1 = UserManager.create_user("user1", "user1@envipath.com", "SuperSafe",
|
||||
set_setting=False, add_to_group=True, is_active=True)
|
||||
cls.user1 = UserManager.create_user(
|
||||
"user1",
|
||||
"user1@envipath.com",
|
||||
"SuperSafe",
|
||||
set_setting=False,
|
||||
add_to_group=True,
|
||||
is_active=True,
|
||||
)
|
||||
cls.user1_default_package = cls.user1.default_package
|
||||
cls.package = PackageManager.create_package(cls.user1, 'Test', 'Test Pack')
|
||||
cls.package = PackageManager.create_package(cls.user1, "Test", "Test Pack")
|
||||
|
||||
def setUp(self):
|
||||
self.client.force_login(self.user1)
|
||||
|
||||
def test_create_rule(self):
|
||||
response = self.client.post(
|
||||
reverse("rules"), {
|
||||
reverse("rules"),
|
||||
{
|
||||
"rule-name": "Test Rule",
|
||||
"rule-description": "Just a Description",
|
||||
"rule-smirks": "[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]",
|
||||
"rule-type": "SimpleAmbitRule",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
@ -38,18 +45,21 @@ class RuleViewTest(TestCase):
|
||||
self.assertEqual(r.package, self.user1_default_package)
|
||||
self.assertEqual(r.name, "Test Rule")
|
||||
self.assertEqual(r.description, "Just a Description")
|
||||
self.assertEqual(r.smirks,
|
||||
"[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]")
|
||||
self.assertEqual(
|
||||
r.smirks,
|
||||
"[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]",
|
||||
)
|
||||
self.assertEqual(self.user1_default_package.rules.count(), 1)
|
||||
|
||||
# Adding the same rule again should return the existing one, hence not increasing the number of rules
|
||||
response = self.client.post(
|
||||
reverse("rules"), {
|
||||
reverse("rules"),
|
||||
{
|
||||
"rule-name": "Test Rule",
|
||||
"rule-description": "Just a Description",
|
||||
"rule-smirks": "[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]",
|
||||
"rule-type": "SimpleAmbitRule",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.url, rule_url)
|
||||
@ -58,12 +68,13 @@ class RuleViewTest(TestCase):
|
||||
|
||||
# Adding the same rule in a different package should create a new rule
|
||||
response = self.client.post(
|
||||
reverse("package rule list", kwargs={'package_uuid': self.package.uuid}), {
|
||||
reverse("package rule list", kwargs={"package_uuid": self.package.uuid}),
|
||||
{
|
||||
"rule-name": "Test Rule",
|
||||
"rule-description": "Just a Description",
|
||||
"rule-smirks": "[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]",
|
||||
"rule-type": "SimpleAmbitRule",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
@ -72,12 +83,13 @@ class RuleViewTest(TestCase):
|
||||
# Edit
|
||||
def test_edit_rule(self):
|
||||
response = self.client.post(
|
||||
reverse("rules"), {
|
||||
reverse("rules"),
|
||||
{
|
||||
"rule-name": "Test Rule",
|
||||
"rule-description": "Just a Description",
|
||||
"rule-smirks": "[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]",
|
||||
"rule-type": "SimpleAmbitRule",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
@ -86,13 +98,17 @@ class RuleViewTest(TestCase):
|
||||
r = Rule.objects.get(url=rule_url)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("package rule detail", kwargs={
|
||||
'package_uuid': str(self.user1_default_package.uuid),
|
||||
'rule_uuid': str(r.uuid)
|
||||
}), {
|
||||
reverse(
|
||||
"package rule detail",
|
||||
kwargs={
|
||||
"package_uuid": str(self.user1_default_package.uuid),
|
||||
"rule_uuid": str(r.uuid),
|
||||
},
|
||||
),
|
||||
{
|
||||
"rule-name": "Test Rule Adjusted",
|
||||
"rule-description": "New Description",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
@ -108,7 +124,7 @@ class RuleViewTest(TestCase):
|
||||
"Test Desc",
|
||||
"2025-10",
|
||||
"soil",
|
||||
[Temperature(interval=Interval(start=20, end=30))]
|
||||
[Temperature(interval=Interval(start=20, end=30))],
|
||||
)
|
||||
|
||||
s2 = Scenario.create(
|
||||
@ -117,16 +133,17 @@ class RuleViewTest(TestCase):
|
||||
"Test Desc2",
|
||||
"2025-10",
|
||||
"soil",
|
||||
[Temperature(interval=Interval(start=10, end=20))]
|
||||
[Temperature(interval=Interval(start=10, end=20))],
|
||||
)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("rules"), {
|
||||
reverse("rules"),
|
||||
{
|
||||
"rule-name": "Test Rule",
|
||||
"rule-description": "Just a Description",
|
||||
"rule-smirks": "[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]",
|
||||
"rule-type": "SimpleAmbitRule",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
@ -134,48 +151,48 @@ class RuleViewTest(TestCase):
|
||||
r = Rule.objects.get(url=rule_url)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("package rule detail", kwargs={
|
||||
'package_uuid': str(r.package.uuid),
|
||||
'rule_uuid': str(r.uuid)
|
||||
}), {
|
||||
"selected-scenarios": [s1.url, s2.url]
|
||||
}
|
||||
reverse(
|
||||
"package rule detail",
|
||||
kwargs={"package_uuid": str(r.package.uuid), "rule_uuid": str(r.uuid)},
|
||||
),
|
||||
{"selected-scenarios": [s1.url, s2.url]},
|
||||
)
|
||||
|
||||
self.assertEqual(len(r.scenarios.all()), 2)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("package rule detail", kwargs={
|
||||
'package_uuid': str(r.package.uuid),
|
||||
'rule_uuid': str(r.uuid)
|
||||
}), {
|
||||
"selected-scenarios": [s1.url]
|
||||
}
|
||||
reverse(
|
||||
"package rule detail",
|
||||
kwargs={"package_uuid": str(r.package.uuid), "rule_uuid": str(r.uuid)},
|
||||
),
|
||||
{"selected-scenarios": [s1.url]},
|
||||
)
|
||||
|
||||
self.assertEqual(len(r.scenarios.all()), 1)
|
||||
self.assertEqual(r.scenarios.first().url, s1.url)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("package rule detail", kwargs={
|
||||
'package_uuid': str(r.package.uuid),
|
||||
'rule_uuid': str(r.uuid)
|
||||
}), {
|
||||
reverse(
|
||||
"package rule detail",
|
||||
kwargs={"package_uuid": str(r.package.uuid), "rule_uuid": str(r.uuid)},
|
||||
),
|
||||
{
|
||||
# We have to set an empty string to avoid that the parameter is removed
|
||||
"selected-scenarios": ""
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(len(r.scenarios.all()), 0)
|
||||
|
||||
def test_copy(self):
|
||||
response = self.client.post(
|
||||
reverse("rules"), {
|
||||
reverse("rules"),
|
||||
{
|
||||
"rule-name": "Test Rule",
|
||||
"rule-description": "Just a Description",
|
||||
"rule-smirks": "[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]",
|
||||
"rule-type": "SimpleAmbitRule",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
@ -183,12 +200,13 @@ class RuleViewTest(TestCase):
|
||||
r = Rule.objects.get(url=rule_url)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("package detail", kwargs={
|
||||
'package_uuid': str(self.package.uuid),
|
||||
}), {
|
||||
"hidden": "copy",
|
||||
"object_to_copy": r.url
|
||||
}
|
||||
reverse(
|
||||
"package detail",
|
||||
kwargs={
|
||||
"package_uuid": str(self.package.uuid),
|
||||
},
|
||||
),
|
||||
{"hidden": "copy", "object_to_copy": r.url},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
@ -202,26 +220,29 @@ class RuleViewTest(TestCase):
|
||||
|
||||
# Copy to the same package should fail
|
||||
response = self.client.post(
|
||||
reverse("package detail", kwargs={
|
||||
'package_uuid': str(r.package.uuid),
|
||||
}), {
|
||||
"hidden": "copy",
|
||||
"object_to_copy": r.url
|
||||
}
|
||||
reverse(
|
||||
"package detail",
|
||||
kwargs={
|
||||
"package_uuid": str(r.package.uuid),
|
||||
},
|
||||
),
|
||||
{"hidden": "copy", "object_to_copy": r.url},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertEqual(response.json()['error'], f"Can't copy object {rule_url} to the same package!")
|
||||
|
||||
self.assertEqual(
|
||||
response.json()["error"], f"Can't copy object {rule_url} to the same package!"
|
||||
)
|
||||
|
||||
def test_delete(self):
|
||||
response = self.client.post(
|
||||
reverse("rules"), {
|
||||
reverse("rules"),
|
||||
{
|
||||
"rule-name": "Test Rule",
|
||||
"rule-description": "Just a Description",
|
||||
"rule-smirks": "[H:5][C:1]([#6:6])([#1,#9,#17,#35,#53:4])[#9,#17,#35,#53]>>[H:5][C:1]([#6:6])([#8])[#1,#9,#17,#35,#53:4]",
|
||||
"rule-type": "SimpleAmbitRule",
|
||||
}
|
||||
},
|
||||
)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
@ -229,12 +250,11 @@ class RuleViewTest(TestCase):
|
||||
r = Rule.objects.get(url=rule_url)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("package rule detail", kwargs={
|
||||
'package_uuid': str(r.package.uuid),
|
||||
'rule_uuid': str(r.uuid)
|
||||
}), {
|
||||
"hidden": "delete"
|
||||
}
|
||||
reverse(
|
||||
"package rule detail",
|
||||
kwargs={"package_uuid": str(r.package.uuid), "rule_uuid": str(r.uuid)},
|
||||
),
|
||||
{"hidden": "delete"},
|
||||
)
|
||||
|
||||
self.assertEqual(self.user1_default_package.rules.count(), 0)
|
||||
|
||||
@ -11,70 +11,81 @@ class UserViewTest(TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(UserViewTest, cls).setUpClass()
|
||||
cls.user = User.objects.get(username='anonymous')
|
||||
cls.package = PackageManager.create_package(cls.user, 'Anon Test Package', 'No Desc')
|
||||
cls.BBD_SUBSET = Package.objects.get(name='Fixtures')
|
||||
cls.user = User.objects.get(username="anonymous")
|
||||
cls.package = PackageManager.create_package(cls.user, "Anon Test Package", "No Desc")
|
||||
cls.BBD_SUBSET = Package.objects.get(name="Fixtures")
|
||||
|
||||
def test_login_with_valid_credentials(self):
|
||||
response = self.client.post(reverse("login"), {
|
||||
"username": "user0",
|
||||
"password": 'SuperSafe',
|
||||
})
|
||||
response = self.client.post(
|
||||
reverse("login"),
|
||||
{
|
||||
"username": "user0",
|
||||
"password": "SuperSafe",
|
||||
},
|
||||
)
|
||||
self.assertRedirects(response, reverse("index"))
|
||||
self.assertTrue(response.wsgi_request.user.is_authenticated)
|
||||
|
||||
def test_login_with_invalid_credentials(self):
|
||||
response = self.client.post(reverse("login"), {
|
||||
"username": "user0",
|
||||
"password": "wrongpassword",
|
||||
})
|
||||
response = self.client.post(
|
||||
reverse("login"),
|
||||
{
|
||||
"username": "user0",
|
||||
"password": "wrongpassword",
|
||||
},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertFalse(response.wsgi_request.user.is_authenticated)
|
||||
|
||||
def test_register(self):
|
||||
response = self.client.post(reverse("register"), {
|
||||
"username": "user1",
|
||||
"email": "user1@envipath.com",
|
||||
"password": "SuperSafe",
|
||||
"rpassword": "SuperSafe",
|
||||
})
|
||||
response = self.client.post(
|
||||
reverse("register"),
|
||||
{
|
||||
"username": "user1",
|
||||
"email": "user1@envipath.com",
|
||||
"password": "SuperSafe",
|
||||
"rpassword": "SuperSafe",
|
||||
},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
# TODO currently fails as the fixture does not provide a global setting...
|
||||
self.assertContains(response, "Registration failed!")
|
||||
|
||||
def test_register_password_mismatch(self):
|
||||
response = self.client.post(reverse("register"), {
|
||||
"username": "user1",
|
||||
"email": "user1@envipath.com",
|
||||
"password": "SuperSafe",
|
||||
"rpassword": "SuperSaf3",
|
||||
})
|
||||
response = self.client.post(
|
||||
reverse("register"),
|
||||
{
|
||||
"username": "user1",
|
||||
"email": "user1@envipath.com",
|
||||
"password": "SuperSafe",
|
||||
"rpassword": "SuperSaf3",
|
||||
},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "Registration failed, provided passwords differ")
|
||||
|
||||
def test_logout(self):
|
||||
response = self.client.post(reverse("login"), {
|
||||
"username": "user0",
|
||||
"password": 'SuperSafe',
|
||||
"login": "true"
|
||||
})
|
||||
response = self.client.post(
|
||||
reverse("login"), {"username": "user0", "password": "SuperSafe", "login": "true"}
|
||||
)
|
||||
self.assertTrue(response.wsgi_request.user.is_authenticated)
|
||||
|
||||
response = self.client.post(reverse('logout'), {
|
||||
"logout": "true",
|
||||
})
|
||||
response = self.client.post(
|
||||
reverse("logout"),
|
||||
{
|
||||
"logout": "true",
|
||||
},
|
||||
)
|
||||
self.assertFalse(response.wsgi_request.user.is_authenticated)
|
||||
|
||||
def test_next_param_properly_handled(self):
|
||||
response = self.client.get(reverse('packages'))
|
||||
response = self.client.get(reverse("packages"))
|
||||
|
||||
self.assertRedirects(response, f"{reverse('login')}/?next=/package")
|
||||
|
||||
response = self.client.post(reverse('login'), {
|
||||
"username": "user0",
|
||||
"password": 'SuperSafe',
|
||||
"login": "true",
|
||||
"next": "/package"
|
||||
})
|
||||
response = self.client.post(
|
||||
reverse("login"),
|
||||
{"username": "user0", "password": "SuperSafe", "login": "true", "next": "/package"},
|
||||
)
|
||||
|
||||
self.assertRedirects(response, reverse('packages'))
|
||||
self.assertRedirects(response, reverse("packages"))
|
||||
|
||||
Reference in New Issue
Block a user