diff --git a/deployment/codeship_runtests.sh b/deployment/codeship_runtests.sh index bc6bf74..4e3e987 100755 --- a/deployment/codeship_runtests.sh +++ b/deployment/codeship_runtests.sh @@ -5,7 +5,7 @@ set -e # fail immediately if any command fails VERSION="${TESTENV}.py${PYVERSION}" -PYTESTFLAGS="-n 2 --disable-warnings --durations=20 --junit-xml=/opt/reports/junit.${VERSION}.xml --timeout=1800 --tb=short" +PYTESTFLAGS="-n 2 --spec --disable-warnings --durations=20 --junit-xml=/opt/reports/junit.${VERSION}.xml --timeout=1800 --tb=short" if [ "${VERSION}" == "complete.py3" ]; then PYTESTFLAGS="--cov moldesign ${PYTESTFLAGS}" fi diff --git a/deployment/requirements.txt b/deployment/requirements.txt index f64d5a6..a9130ea 100644 --- a/deployment/requirements.txt +++ b/deployment/requirements.txt @@ -1,9 +1,11 @@ # Python dependencies for the build/test environment coveralls nbformat -pathlib ; python_version < '3.5' +pathlib ; python_version < '3.3' PyGithub +pyccc >= 0.7.10 pytest-cov pytest-xdist != 1.17.0 pytest-timeout +pytest-spec diff --git a/moldesign/_tests/test_constraints.py b/moldesign/_tests/test_constraints.py index ce39101..032aa5a 100644 --- a/moldesign/_tests/test_constraints.py +++ b/moldesign/_tests/test_constraints.py @@ -6,7 +6,7 @@ import moldesign as mdt from moldesign import units as u - +from .molecule_fixtures import * from . import helpers registered_types = {} @@ -163,3 +163,29 @@ def test_dihedral_constraint_errors_at_0(four_particle_45_twist): constraint.value = angle np.testing.assert_allclose(constraint.error().value_in(u.degrees), -angle.magnitude) + +def test_cannot_add_duplicate_constraints(parameterize_zeros): + mol = parameterize_zeros + mol.constrain_distance(*mol.atoms[:2]) + mol.constrain_angle(*mol.atoms[:3]) + mol.constrain_dihedral(*mol.atoms[:4]) + mol.constrain_atom(mol.atoms[0]) + mol.constrain_hbonds() + + # Failure on adding duplicates + with pytest.raises(KeyError): + mol.constrain_distance(*mol.atoms[:2]) + with pytest.raises(KeyError): + mol.constrain_angle(*mol.atoms[:3]) + with pytest.raises(KeyError): + mol.constrain_dihedral(*mol.atoms[:4]) + with pytest.raises(KeyError): + mol.constrain_atom(mol.atoms[0]) + with pytest.raises(KeyError): + mol.constrain_hbonds() + + # These should be ok + mol.constrain_distance(*mol.atoms[1:3]) + mol.constrain_angle(*mol.atoms[1:4]) + mol.constrain_dihedral(*mol.atoms[1:5]) + mol.constrain_atom(mol.atoms[1]) diff --git a/moldesign/_tests/test_copies.py b/moldesign/_tests/test_copies.py index 3be5397..a71ef1d 100644 --- a/moldesign/_tests/test_copies.py +++ b/moldesign/_tests/test_copies.py @@ -35,7 +35,7 @@ def test_copy_breaks_link(h2): assert h2.atoms[1].px == 0.0 * u.default.momentum -def test_h2_harmonic_copy_loses_simulation(h2_harmonic_copy, h2_harmonic): +def test_h2_harmonic_copy(h2_harmonic_copy, h2_harmonic): mol = h2_harmonic_copy assert mol.energy_model is mol.integrator is None for name in 'num_atoms num_residues positions momenta'.split(): @@ -196,6 +196,7 @@ def test_constraints_copied_with_molecule(parameterize_zeros): mol.constrain_hbonds() mcpy = mol.copy() + assert isinstance(mcpy.constraints, mol.constraints.__class__) assert mcpy.constraints[0].desc == 'distance' assert mcpy.constraints[1].desc == 'angle' assert mcpy.constraints[2].desc == 'dihedral' diff --git a/moldesign/molecules/molecule.py b/moldesign/molecules/molecule.py index 525eecc..6cb6eb1 100644 --- a/moldesign/molecules/molecule.py +++ b/moldesign/molecules/molecule.py @@ -1074,8 +1074,9 @@ def __init__(self, atomcontainer, self.name = 'uninitialized molecule' self._defres = None self._defchain = None + self._constraints = None self.pdbname = pdbname - self.constraints = utils.ExclusiveList(key=utils.methodcaller('_constraintsig')) + self.constraints = [] self.energy_model = None self.integrator = None self.metadata = metadata @@ -1133,6 +1134,14 @@ def __repr__(self): def __str__(self): return 'Molecule: %s' % self.name + @property + def constraints(self): + return self._constraints + + @constraints.setter + def constraints(self, val): + self._constraints = utils.ExclusiveList(val, key=utils.methodcaller('_constraintsig')) + def _repr_markdown_(self): """A markdown description of this molecule.