Source code for schrodinger.test
# flake8: noqa
import contextlib
import inspect
import io
import logging
import os
import sys
import typing
from pathlib import Path
# For documentation, please see schrodinger/test/testfiles.h
from schrodinger.infra.test import internal_data_file
from schrodinger.infra.test import mmshare_data_file
from schrodinger.infra.test import mmshare_testfile
from schrodinger.utils.env import prepend_sys_path
[docs]def relpath_from_testdir(*path_components):
"""
Absolute path to a file in the same directory as the calling code.
"""
stk = inspect.stack()
caller_path = stk[1][1]
caller_dir = os.path.abspath(os.path.dirname(caller_path))
return os.path.join(caller_dir, *path_components)
[docs]def assert_structures_identical(st1, st2, tolerance=1e-6):
"""
Determines if the given two structures are exactly the same. Specifically,
determines if the two structures have the same atoms with the same properties
and bonds in the same order.
:param st1: First structure to compare
:type st1: Structure
:param st2: Second structure to compare
:type st2: Structure
:param float tolerance: Absolute tolerance for comparing fractional atom and
bond properties. Relative tolerance is not supported
because properties read from file are limited to six
decimal places, so this assertion might return false
depending on the absolute value of the property.
"""
# Prevent circular dependencies
from schrodinger.test import custom_assertions
custom_assertions.assert_properties_match(st1,
st2,
ignore=['i_m_ct_format'])
custom_assertions.assertSameNumberOfAtoms(st1, st2)
for at1, at2 in zip(list(st1.atom), list(st2.atom)):
# Check at1 and at2 have the same properties
custom_assertions.assertEqualDicts(dict(at1.property),
dict(at2.property),
tolerance=tolerance)
# Check that at1 and at2 have the same bonds and bond types
assert len(at1.bond) == len(at2.bond)
prop_names = ('Atom 1 Index', 'Atom 2 Index', 'Bond Type')
bonds1 = sorted([
(int(b.atom1), int(b.atom2), b.type) for b in list(at1.bond)
])
bonds2 = sorted([
(int(b.atom1), int(b.atom2), b.type) for b in list(at2.bond)
])
for b1, b2 in zip(bonds1, bonds2):
for prop1, prop2, prop_name in zip(b1, b2, prop_names):
assert prop1 == prop2, f"Bond {b1} in at1 and bond {b2} in at2 are different."
a1_bonds = list(at1.bond)
a2_bonds = list(at2.bond)
a1_bonds.sort(key=lambda bnd: sorted([int(bnd.atom1), int(bnd.atom2)]))
a2_bonds.sort(key=lambda bnd: sorted([int(bnd.atom1), int(bnd.atom2)]))
for a1_bond, a2_bond in zip(a1_bonds, a2_bonds):
custom_assertions.assertEqualDicts(a1_bond.property,
a2_bond.property,
tolerance=tolerance)
[docs]def mmshare_source_dir():
return Path(os.environ["SCHRODINGER_SRC"]) / "mmshare"
[docs]def mmshare_nondist_dir():
return mmshare_source_dir() / "python" / "nondist"
[docs]@contextlib.contextmanager
def add_nondist_to_path():
with prepend_sys_path(mmshare_nondist_dir()):
yield
[docs]@contextlib.contextmanager
def stringio_handler(logger: logging.Logger) -> typing.Iterator[io.StringIO]:
"""
Temporarily add a StringIO as the stream of a handler in order to assert
output of log.
"""
stream = io.StringIO()
handler = logging.StreamHandler(stream)
logger.addHandler(handler)
yield stream
logger.removeHandler(handler)