feat(toolkit): ship macro_lactone_toolkit package
Unify macrolactone detection, numbering, fragmentation, and splicing under the installable macro_lactone_toolkit package. - replace legacy src.* modules with the new package layout - add analyze/number/fragment CLI entrypoints and pixi tasks - migrate tests, README, and scripts to the new package API
This commit is contained in:
73
tests/test_detection_and_numbering.py
Normal file
73
tests/test_detection_and_numbering.py
Normal file
@@ -0,0 +1,73 @@
|
||||
import pytest
|
||||
from rdkit import Chem
|
||||
|
||||
from macro_lactone_toolkit import (
|
||||
AmbiguousMacrolactoneError,
|
||||
MacroLactoneAnalyzer,
|
||||
MacrolactoneDetectionError,
|
||||
MacrolactoneFragmenter,
|
||||
)
|
||||
|
||||
from .helpers import build_ambiguous_smiles, build_macrolactone
|
||||
|
||||
|
||||
@pytest.mark.parametrize("ring_size", [12, 14, 16, 20])
|
||||
def test_analyzer_detects_supported_ring_sizes(ring_size: int):
|
||||
built = build_macrolactone(ring_size)
|
||||
analyzer = MacroLactoneAnalyzer()
|
||||
|
||||
assert analyzer.get_valid_ring_sizes(built.smiles) == [ring_size]
|
||||
|
||||
|
||||
def test_analyzer_rejects_non_lactone_macrocycle():
|
||||
analyzer = MacroLactoneAnalyzer()
|
||||
|
||||
assert analyzer.get_valid_ring_sizes("C1CCCCCCCCCCC1") == []
|
||||
|
||||
|
||||
def test_fragmenter_auto_numbers_ring_with_expected_positions():
|
||||
built = build_macrolactone(16, {5: "methyl"})
|
||||
result = MacrolactoneFragmenter().number_molecule(built.mol)
|
||||
|
||||
assert result.ring_size == 16
|
||||
assert result.position_to_atom == built.position_to_atom
|
||||
assert set(result.position_to_atom) == set(range(1, 17))
|
||||
assert result.atom_to_position == {
|
||||
atom_idx: position for position, atom_idx in built.position_to_atom.items()
|
||||
}
|
||||
|
||||
carbonyl_atom = built.mol.GetAtomWithIdx(result.position_to_atom[1])
|
||||
assert carbonyl_atom.GetSymbol() == "C"
|
||||
assert any(
|
||||
bond.GetBondType() == Chem.BondType.DOUBLE and bond.GetOtherAtom(carbonyl_atom).GetSymbol() == "O"
|
||||
for bond in carbonyl_atom.GetBonds()
|
||||
)
|
||||
|
||||
ester_oxygen = built.mol.GetAtomWithIdx(result.position_to_atom[2])
|
||||
assert ester_oxygen.GetSymbol() == "O"
|
||||
|
||||
|
||||
def test_fragmenter_requires_explicit_ring_size_for_ambiguous_molecule():
|
||||
ambiguous_smiles = build_ambiguous_smiles()
|
||||
|
||||
with pytest.raises(AmbiguousMacrolactoneError):
|
||||
MacrolactoneFragmenter().number_molecule(ambiguous_smiles)
|
||||
|
||||
|
||||
def test_fragmenter_raises_for_missing_macrolactone():
|
||||
with pytest.raises(MacrolactoneDetectionError):
|
||||
MacrolactoneFragmenter().number_molecule("CCO")
|
||||
|
||||
|
||||
def test_explicit_ring_size_selects_requested_ring():
|
||||
built = build_macrolactone(14)
|
||||
result = MacrolactoneFragmenter(ring_size=14).number_molecule(built.smiles)
|
||||
|
||||
assert result.ring_size == 14
|
||||
|
||||
|
||||
def test_explicit_ring_size_rejects_wrong_ring():
|
||||
built = build_macrolactone(12)
|
||||
|
||||
with pytest.raises(MacrolactoneDetectionError):
|
||||
MacrolactoneFragmenter(ring_size=16).number_molecule(built.smiles)
|
||||
Reference in New Issue
Block a user