10 from __future__
import print_function, division, absolute_import
15 from sys
import version_info
as _swig_python_version_info
16 if _swig_python_version_info >= (2, 7, 0):
17 def swig_import_helper():
19 pkg = __name__.rpartition(
'.')[0]
20 mname =
'.'.join((pkg,
'_IMP_test')).lstrip(
'.')
22 return importlib.import_module(mname)
24 return importlib.import_module(
'_IMP_test')
25 _IMP_test = swig_import_helper()
26 del swig_import_helper
27 elif _swig_python_version_info >= (2, 6, 0):
28 def swig_import_helper():
29 from os.path
import dirname
33 fp, pathname, description = imp.find_module(
'_IMP_test', [dirname(__file__)])
39 _mod = imp.load_module(
'_IMP_test', fp, pathname, description)
43 _IMP_test = swig_import_helper()
44 del swig_import_helper
47 del _swig_python_version_info
49 _swig_property = property
54 import builtins
as __builtin__
58 def _swig_setattr_nondynamic(self, class_type, name, value, static=1):
59 if (name ==
"thisown"):
60 return self.this.own(value)
62 if type(value).__name__ ==
'SwigPyObject':
63 self.__dict__[name] = value
65 method = class_type.__swig_setmethods__.get(name,
None)
67 return method(self, value)
69 object.__setattr__(self, name, value)
71 raise AttributeError(
"You cannot add attributes to %s" % self)
74 def _swig_setattr(self, class_type, name, value):
75 return _swig_setattr_nondynamic(self, class_type, name, value, 0)
78 def _swig_getattr(self, class_type, name):
79 if (name ==
"thisown"):
80 return self.this.own()
81 method = class_type.__swig_getmethods__.get(name,
None)
84 raise AttributeError(
"'%s' object has no attribute '%s'" % (class_type.__name__, name))
89 strthis =
"proxy of " + self.this.__repr__()
90 except __builtin__.Exception:
92 return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
95 def _swig_setattr_nondynamic_method(set):
96 def set_attr(self, name, value):
97 if (name ==
"thisown"):
98 return self.this.own(value)
99 if hasattr(self, name)
or (name ==
"this"):
100 set(self, name, value)
102 raise AttributeError(
"You cannot add attributes to %s" % self)
108 weakref_proxy = weakref.proxy
109 except __builtin__.Exception:
110 weakref_proxy =
lambda x: x
113 class IMP_TEST_SwigPyIterator(object):
114 """Proxy of C++ swig::IMP_TEST_SwigPyIterator class."""
116 thisown = _swig_property(
lambda x: x.this.own(),
lambda x, v: x.this.own(v), doc=
'The membership flag')
118 def __init__(self, *args, **kwargs):
119 raise AttributeError(
"No constructor defined - class is abstract")
120 __repr__ = _swig_repr
121 __swig_destroy__ = _IMP_test.delete_IMP_TEST_SwigPyIterator
122 __del__ =
lambda self:
None
125 """value(IMP_TEST_SwigPyIterator self) -> PyObject *"""
126 return _IMP_test.IMP_TEST_SwigPyIterator_value(self)
131 incr(IMP_TEST_SwigPyIterator self, size_t n=1) -> IMP_TEST_SwigPyIterator
132 incr(IMP_TEST_SwigPyIterator self) -> IMP_TEST_SwigPyIterator
134 return _IMP_test.IMP_TEST_SwigPyIterator_incr(self, n)
139 decr(IMP_TEST_SwigPyIterator self, size_t n=1) -> IMP_TEST_SwigPyIterator
140 decr(IMP_TEST_SwigPyIterator self) -> IMP_TEST_SwigPyIterator
142 return _IMP_test.IMP_TEST_SwigPyIterator_decr(self, n)
145 def distance(self, x):
146 """distance(IMP_TEST_SwigPyIterator self, IMP_TEST_SwigPyIterator x) -> ptrdiff_t"""
147 return _IMP_test.IMP_TEST_SwigPyIterator_distance(self, x)
151 """equal(IMP_TEST_SwigPyIterator self, IMP_TEST_SwigPyIterator x) -> bool"""
152 return _IMP_test.IMP_TEST_SwigPyIterator_equal(self, x)
156 """copy(IMP_TEST_SwigPyIterator self) -> IMP_TEST_SwigPyIterator"""
157 return _IMP_test.IMP_TEST_SwigPyIterator_copy(self)
161 """next(IMP_TEST_SwigPyIterator self) -> PyObject *"""
162 return _IMP_test.IMP_TEST_SwigPyIterator_next(self)
166 """__next__(IMP_TEST_SwigPyIterator self) -> PyObject *"""
167 return _IMP_test.IMP_TEST_SwigPyIterator___next__(self)
171 """previous(IMP_TEST_SwigPyIterator self) -> PyObject *"""
172 return _IMP_test.IMP_TEST_SwigPyIterator_previous(self)
175 def advance(self, n):
176 """advance(IMP_TEST_SwigPyIterator self, ptrdiff_t n) -> IMP_TEST_SwigPyIterator"""
177 return _IMP_test.IMP_TEST_SwigPyIterator_advance(self, n)
181 """__eq__(IMP_TEST_SwigPyIterator self, IMP_TEST_SwigPyIterator x) -> bool"""
182 return _IMP_test.IMP_TEST_SwigPyIterator___eq__(self, x)
186 """__ne__(IMP_TEST_SwigPyIterator self, IMP_TEST_SwigPyIterator x) -> bool"""
187 return _IMP_test.IMP_TEST_SwigPyIterator___ne__(self, x)
190 def __iadd__(self, n):
191 """__iadd__(IMP_TEST_SwigPyIterator self, ptrdiff_t n) -> IMP_TEST_SwigPyIterator"""
192 return _IMP_test.IMP_TEST_SwigPyIterator___iadd__(self, n)
195 def __isub__(self, n):
196 """__isub__(IMP_TEST_SwigPyIterator self, ptrdiff_t n) -> IMP_TEST_SwigPyIterator"""
197 return _IMP_test.IMP_TEST_SwigPyIterator___isub__(self, n)
200 def __add__(self, n):
201 """__add__(IMP_TEST_SwigPyIterator self, ptrdiff_t n) -> IMP_TEST_SwigPyIterator"""
202 return _IMP_test.IMP_TEST_SwigPyIterator___add__(self, n)
205 def __sub__(self, *args):
207 __sub__(IMP_TEST_SwigPyIterator self, ptrdiff_t n) -> IMP_TEST_SwigPyIterator
208 __sub__(IMP_TEST_SwigPyIterator self, IMP_TEST_SwigPyIterator x) -> ptrdiff_t
210 return _IMP_test.IMP_TEST_SwigPyIterator___sub__(self, *args)
214 IMP_TEST_SwigPyIterator_swigregister = _IMP_test.IMP_TEST_SwigPyIterator_swigregister
215 IMP_TEST_SwigPyIterator_swigregister(IMP_TEST_SwigPyIterator)
223 IMP_DEBUG = _IMP_test.IMP_DEBUG
224 IMP_RELEASE = _IMP_test.IMP_RELEASE
225 IMP_SILENT = _IMP_test.IMP_SILENT
226 IMP_PROGRESS = _IMP_test.IMP_PROGRESS
227 IMP_TERSE = _IMP_test.IMP_TERSE
228 IMP_VERBOSE = _IMP_test.IMP_VERBOSE
229 IMP_MEMORY = _IMP_test.IMP_MEMORY
230 IMP_NONE = _IMP_test.IMP_NONE
231 IMP_USAGE = _IMP_test.IMP_USAGE
232 IMP_INTERNAL = _IMP_test.IMP_INTERNAL
233 IMP_KERNEL_HAS_LOG4CXX = _IMP_test.IMP_KERNEL_HAS_LOG4CXX
234 IMP_COMPILER_HAS_AUTO = _IMP_test.IMP_COMPILER_HAS_AUTO
235 IMP_COMPILER_HAS_DEBUG_VECTOR = _IMP_test.IMP_COMPILER_HAS_DEBUG_VECTOR
236 IMP_COMPILER_HAS_UNIQUE_PTR = _IMP_test.IMP_COMPILER_HAS_UNIQUE_PTR
237 IMP_KERNEL_HAS_BOOST_RANDOM = _IMP_test.IMP_KERNEL_HAS_BOOST_RANDOM
238 IMP_KERNEL_HAS_GPERFTOOLS = _IMP_test.IMP_KERNEL_HAS_GPERFTOOLS
239 IMP_KERNEL_HAS_TCMALLOC_HEAPCHECKER = _IMP_test.IMP_KERNEL_HAS_TCMALLOC_HEAPCHECKER
240 IMP_KERNEL_HAS_TCMALLOC_HEAPPROFILER = _IMP_test.IMP_KERNEL_HAS_TCMALLOC_HEAPPROFILER
241 IMPKERNEL_SHOW_WARNINGS = _IMP_test.IMPKERNEL_SHOW_WARNINGS
244 class _DirectorObjects(object):
245 """@internal Simple class to keep references to director objects
246 to prevent premature deletion."""
249 def register(self, obj):
250 """Take a reference to a director object; will only work for
251 refcounted C++ classes"""
252 if hasattr(obj,
'get_ref_count'):
253 self._objects.append(obj)
255 """Only drop our reference and allow cleanup by Python if no other
256 Python references exist (we hold 3 references: one in self._objects,
257 one in x, and one in the argument list for getrefcount) *and* no
258 other C++ references exist (the Python object always holds one)"""
259 objs = [x
for x
in self._objects
if sys.getrefcount(x) > 3 \
260 or x.get_ref_count() > 1]
264 def get_object_count(self):
265 """Get number of director objects (useful for testing only)"""
266 return len(self._objects)
267 _director_objects = _DirectorObjects()
269 class _ostream(object):
270 """Proxy of C++ std::ostream class."""
272 thisown = _swig_property(
lambda x: x.this.own(),
lambda x, v: x.this.own(v), doc=
'The membership flag')
274 def __init__(self, *args, **kwargs):
275 raise AttributeError(
"No constructor defined")
276 __repr__ = _swig_repr
278 def write(self, osa_buf):
279 """write(_ostream self, char const * osa_buf)"""
280 return _IMP_test._ostream_write(self, osa_buf)
282 _ostream_swigregister = _IMP_test._ostream_swigregister
283 _ostream_swigregister(_ostream)
285 IMP_COMPILER_HAS_OVERRIDE = _IMP_test.IMP_COMPILER_HAS_OVERRIDE
286 IMP_COMPILER_HAS_FINAL = _IMP_test.IMP_COMPILER_HAS_FINAL
287 IMP_HAS_NOEXCEPT = _IMP_test.IMP_HAS_NOEXCEPT
288 IMP_C_OPEN_BINARY = _IMP_test.IMP_C_OPEN_BINARY
290 IMP_TEST_HAS_BOOST_FILESYSTEM = _IMP_test.IMP_TEST_HAS_BOOST_FILESYSTEM
291 IMP_TEST_HAS_BOOST_PROGRAMOPTIONS = _IMP_test.IMP_TEST_HAS_BOOST_PROGRAMOPTIONS
292 IMP_TEST_HAS_BOOST_RANDOM = _IMP_test.IMP_TEST_HAS_BOOST_RANDOM
293 IMP_TEST_HAS_BOOST_SYSTEM = _IMP_test.IMP_TEST_HAS_BOOST_SYSTEM
294 IMPTEST_SHOW_WARNINGS = _IMP_test.IMPTEST_SHOW_WARNINGS
297 """@namespace IMP::test
298 @brief Methods and classes for testing the IMP kernel and modules.
314 from .
import _compat_python
315 from ._compat_python
import unittest2
316 from ._compat_python.unittest2.util
import safe_repr
333 def __load_unittest_package():
335 for modname, fromlist
in ((
'unittest', []),
339 u = __import__(modname, {}, {}, fromlist)
340 if hasattr(u,
'skip'):
343 errors.append(
"'%s' does not have the 'skip' decorator" \
345 except ImportError
as e:
346 errors.append(str(e))
348 return _compat_python.unittest2
349 raise ImportError(
"IMP.test requires a newer version of Python's unittest "
350 "package than is available. Either upgrade to a new "
351 "enough Python (at least 2.7 or 3.2) or install the "
352 "unittest2 package. Encountered errors: %s" \
354 unittest = __load_unittest_package()
357 expectedFailure = unittest.expectedFailure
359 skipIf = unittest.skipIf
360 skipUnless = unittest.skipUnless
364 """Simple RAII-style class to run in a temporary directory.
365 When the object is created, the temporary directory is created
366 and becomes the current working directory. When the object goes out
367 of scope, the working directory is reset and the temporary directory
370 self.origdir = os.getcwd()
371 self.tmpdir = tempfile.mkdtemp()
372 os.chdir(self.tmpdir)
374 os.chdir(self.origdir)
375 shutil.rmtree(self.tmpdir, ignore_errors=
True)
377 @contextlib.contextmanager
379 """Simple context manager to run in a temporary directory.
380 While the context manager is active (within the 'with' block)
381 the current working directory is set to a temporary directory.
382 When the context manager exists, the working directory is reset
383 and the temporary directory deleted."""
384 origdir = os.getcwd()
385 tmpdir = tempfile.mkdtemp()
389 shutil.rmtree(tmpdir, ignore_errors=
True)
393 """Simple RAII-style class to make a temporary directory. When the object
394 is created, the temporary directory is created. When the object goes
395 out of scope, the temporary directory is deleted."""
396 def __init__(self, dir=None):
397 self.tmpdir = tempfile.mkdtemp(dir=dir)
399 shutil.rmtree(self.tmpdir, ignore_errors=
True)
401 class _TempDir(object):
402 def __init__(self, dir=None):
403 self.tmpdir = tempfile.mkdtemp(dir=dir)
405 shutil.rmtree(self.tmpdir, ignore_errors=
True)
407 @contextlib.contextmanager
409 """Simple context manager to make a temporary directory.
410 The temporary directory has the same lifetime as the context manager
411 (i.e. it is created at the start of the 'with' block, and deleted
412 at the end of the block).
413 @param dir If given, the temporary directory is made as a subdirectory
414 of that directory, rather than in the default temporary
415 directory location (e.g. /tmp)
416 @return the full path to the temporary directory.
418 tmpdir = tempfile.mkdtemp(dir=dir)
420 shutil.rmtree(tmpdir, ignore_errors=
True)
423 """Calculate the derivative of the single-value function `func` at
424 point `val`. The derivative is calculated using simple finite
425 differences starting with the given `step`; Richardson extrapolation
426 is then used to extrapolate the derivative at step=0."""
431 f1 = func(val + step)
432 f2 = func(val - step)
434 d = [[(f1 - f2) / (2.0 * step)]]
436 for i
in range(1, maxsteps):
437 d.append([0.] * (i + 1))
439 f1 = func(val + step)
440 f2 = func(val - step)
441 d[i][0] = (f1 - f2) / (2.0 * step)
443 for j
in range(1, i + 1):
444 d[i][j] = (d[i][j-1] * fac - d[i-1][j-1]) / (fac - 1.)
446 errt = max(abs(d[i][j] - d[i][j-1]),
447 abs(d[i][j] - d[i-1][j-1]))
451 if abs(d[i][i] - d[i-1][i-1]) >= safe * err:
454 raise ValueError(
"Cannot calculate numerical derivative")
459 """Calculate the x,y and z derivatives of the scoring function `sf`
460 on the `xyz` particle. The derivatives are approximated numerically
461 using the numerical_derivatives() function."""
462 class _XYZDerivativeFunc(object):
463 def __init__(self, sf, xyz, basis_vector):
466 self._basis_vector = basis_vector
467 self._starting_coordinates = xyz.get_coordinates()
469 def __call__(self, val):
470 self._xyz.set_coordinates(self._starting_coordinates + \
471 self._basis_vector * val)
472 return self._sf.evaluate(
False)
476 for x
in ((1,0,0), (0,1,0), (0,0,1))])
480 """Super class for IMP test cases.
481 This provides a number of useful IMP-specific methods on top of
482 the standard Python `unittest.TestCase` class.
483 Test scripts should generally contain a subclass of this class,
484 conventionally called `Tests` (this makes it easier to run an
485 individual test from the commane line) and use IMP::test::main()
486 as their main function."""
490 if not hasattr(unittest.TestCase,
'assertRegex'):
491 assertRegex = unittest.TestCase.assertRegexpMatches
492 assertNotRegex = unittest.TestCase.assertNotRegexpMatches
494 def __init__(self, *args, **keys):
495 unittest.TestCase.__init__(self, *args, **keys)
496 self._progname = os.path.abspath(sys.argv[0])
504 IMP.random_number_generator.seed(hash(time.time())%2**30)
510 if hasattr(self,
'_tmpdir'):
514 """Get the full name of an input file in the top-level
516 testdir = os.path.dirname(self._progname)
517 if self.__module__ !=
'__main__':
518 testdir = os.path.dirname(sys.modules[self.__module__].__file__)
519 dirs = testdir.split(os.path.sep)
520 for i
in range(len(dirs), 0, -1):
521 input = os.path.sep.join(dirs[:i] + [
'input'])
522 if os.path.isdir(input):
523 ret = os.path.join(input, filename)
524 if not os.path.exists(ret):
525 raise IOError(
"Test input file "+ret+
" does not exist")
527 raise IOError(
"No test input directory found")
530 """Open and return an input file in the top-level test directory."""
534 """Get the full name of an output file in the tmp directory.
535 The directory containing this file will be automatically
536 cleaned up when the test completes."""
537 if not hasattr(self,
'_tmpdir'):
538 self._tmpdir = _TempDir(os.environ[
'IMP_TMP_DIR'])
539 tmpdir = self._tmpdir.tmpdir
540 return os.path.join(tmpdir, filename)
543 """Get the magnitude of a list of floats"""
544 return sum([x*x
for x
in vector], 0)**.5
547 """Assert that the given callable object raises UsageException.
548 This differs from unittest's assertRaises in that the test
549 is skipped in fast mode (where usage checks are turned off)."""
554 """Assert that the given callable object raises InternalException.
555 This differs from unittest's assertRaises in that the test
556 is skipped in fast mode (where internal checks are turned off)."""
561 """Assert that the given callable object is not implemented."""
566 """Assert that x,y,z analytical derivatives match numerical within
567 a tolerance, or a percentage (of the analytical value), whichever
568 is larger. `sf` should be a ScoringFunction or Restraint,
569 although for backwards compatibility a Model is also accepted."""
571 derivs = xyz.get_derivatives()
573 pct = percentage / 100.0
574 self.assertAlmostEqual(self.
get_magnitude(derivs-num_derivs),0,
576 msg=
"Don't match "+str(derivs) + str(num_derivs))
577 self.assertAlmostEqual(derivs[0], num_derivs[0],
578 delta=max(tolerance, abs(derivs[0]) * pct))
579 self.assertAlmostEqual(derivs[1], num_derivs[1],
580 delta=max(tolerance, abs(derivs[1]) * pct))
581 self.assertAlmostEqual(derivs[2], num_derivs[2],
582 delta=max(tolerance, abs(derivs[2]) * pct))
586 """Fail if the difference between any two items in the two sequences
587 are exceed the specified number of places or delta. See
590 if delta
is not None and places
is not None:
591 raise TypeError(
"specify delta or places not both")
594 ftypename = ftype.__name__
596 stypename = stype.__name__
598 raise self.failureException(
599 'Sequences are of different types: %s != %s' % (
600 ftypename, stypename))
604 except (NotImplementedError, TypeError):
605 raise self.failureException(
606 'First %s has no length' % (ftypename))
609 except (NotImplementedError, TypeError):
610 raise self.failureException(
611 'Second %s has no length' % (stypename))
614 raise self.failureException(
615 'Sequences have non equal lengths: %d != %d' % (flen, slen))
618 for i
in range(min(flen, slen)):
619 differing =
'%ss differ: %s != %s\n' % (
620 ftypename.capitalize(), safe_repr(first),
625 except (TypeError, IndexError, NotImplementedError):
626 differing += (
'\nUnable to index element %d of first %s\n' %
632 except (TypeError, IndexError, NotImplementedError):
633 differing += (
'\nUnable to index element %d of second %s\n' %
638 self.assertAlmostEqual(
639 f, s, places=places, msg=msg, delta=delta)
640 except (TypeError, ValueError, NotImplementedError, AssertionError):
642 "\nFirst differing element "
643 "%d:\n%s\n%s\n") % (i, safe_repr(f), safe_repr(s))
648 standardMsg = differing
649 diffMsg =
'\n' +
'\n'.join(
650 difflib.ndiff(pprint.pformat(first).splitlines(),
651 pprint.pformat(second).splitlines()))
652 standardMsg = self._truncateMessage(standardMsg, diffMsg)
653 msg = self._formatMessage(msg, standardMsg)
654 raise self.failureException(msg)
657 """Make a particle with optimizable x, y and z attributes, and
658 add it to the model."""
666 """Help handle a test which is expected to fail some fraction of
667 the time. The test is run multiple times and an exception
668 is thrown only if it fails too many times.
669 @note Use of this function should be avoided. If there is a corner
670 case that results in a test 'occasionally' failing, write a
671 new test specifically for that corner case and assert that
672 it fails consistently (and remove the corner case from the
675 prob=chance_of_failure
679 prob= prob*chance_of_failure
680 for i
in range(0, tries):
688 raise AssertError(
"Too many failures")
691 """Estimate how likely a given block of code is to raise an
695 while failures < 10
and tries <1000:
701 return failures/tries
704 """Randomize the xyz coordinates of a list of particles"""
710 p.set_value(xkey, random.uniform(-deviation, deviation))
711 p.set_value(ykey, random.uniform(-deviation, deviation))
712 p.set_value(zkey, random.uniform(-deviation, deviation))
715 """Return distance between two given particles"""
719 dx = p1.get_value(xkey) - p2.get_value(xkey)
720 dy = p1.get_value(ykey) - p2.get_value(ykey)
721 dz = p1.get_value(zkey) - p2.get_value(zkey)
722 return math.sqrt(dx*dx + dy*dy + dz*dz)
725 """Check the unary function func's derivatives against numerical
726 approximations between lb and ub"""
727 for f
in [lb + i * step
for i
in range(1, int((ub-lb)/step))]:
728 (v,d)= func.evaluate_with_derivative(f)
730 self.assertAlmostEqual(d, da, delta=max(abs(.1 *d), 0.01))
733 """Make sure that the minimum of the unary function func over the
734 range between lb and ub is at expected_fmin"""
735 fmin, vmin = lb, func.evaluate(lb)
736 for f
in [lb + i * step
for i
in range(1, int((ub-lb)/step))]:
740 self.assertAlmostEqual(fmin, expected_fmin, delta=step)
743 """Check methods that every IMP::Object class should have"""
744 obj.set_was_used(
True)
747 self.assertIsNotNone(cls.get_from(obj))
748 self.assertRaises(ValueError, cls.get_from,
IMP.Model())
750 self.assertIsInstance(str(obj), str)
751 self.assertIsInstance(repr(obj), str)
753 verinf = obj.get_version_info()
762 """Create a bunch of particles in a box"""
767 for i
in range(0,num):
772 def _get_type(self, module, name):
773 return eval(
'type('+module+
"."+name+
')')
775 "Check that all the C++ classes in the module are values or objects."
777 ok = set(exceptions_list + module._value_types + module._object_types + module._raii_types + module._plural_types)
781 if self._get_type(module.__name__, name)==type
and not name.startswith(
"_"):
782 if name.find(
"SwigPyIterator") != -1:
785 if not eval(
'hasattr(%s.%s, "__swig_destroy__")' \
786 % (module.__name__, name)):
791 message=
"All IMP classes should be labeled as values or objects to get memory management correct in Python. The following are not:\n%s\nPlease add an IMP_SWIG_OBJECT or IMP_SWIG_VALUE call to the Python wrapper, or if the class has a good reason to be neither, add the name to the value_object_exceptions list in the IMPModuleTest call." \
793 self.assertEqual(len(bad), 0, message)
794 for e
in exceptions_list:
795 self.assertTrue(e
not in module._value_types
796 + module._object_types
798 + module._plural_types,
799 "Value/Object exception "+e+
" is not an exception")
801 def _check_spelling(self, word, words):
802 """Check that the word is spelled correctly"""
803 if "words" not in dir(self):
805 wordlist= fh.read().split("\n")
807 custom_words=[
"info",
"prechange",
"int",
"ints",
"optimizeds",
"graphviz",
808 "voxel",
"voxels",
"endian",
'rna',
'dna',
809 "xyzr",
"pdbs",
"fft",
"ccc",
"gaussian"]
812 exclude_words = set([
"adapter",
"grey"])
813 self.words=set(wordlist+custom_words) - exclude_words
815 for i
in "0123456789":
820 if word
in self.words:
827 """Check that all the classes in the module follow the IMP
828 naming conventions."""
832 cc=re.compile(
"([A-Z][a-z]*)")
834 if self._get_type(module.__name__, name)==type
and not name.startswith(
"_"):
835 if name.find(
"SwigPyIterator") != -1:
837 for t
in re.findall(cc, name):
838 if not self._check_spelling(t.lower(), words):
839 misspelled.append(t.lower())
842 self.assertEqual(len(bad), 0,
843 "All IMP classes should be properly spelled. The following are not: %s.\nMisspelled words: %s. Add words to the spelling_exceptions variable of the IMPModuleTest if needed." \
844 % (str(bad),
", ".join(set(misspelled))))
847 if self._get_type(module.__name__, name)==type
and not name.startswith(
"_"):
848 if name.find(
"SwigPyIterator") != -1:
850 if name.find(
'_') != -1:
852 if name.lower== name:
854 for t
in re.findall(cc, name):
855 if not self._check_spelling(t.lower(), words):
856 print(
"misspelled %s in %s" % (t, name))
858 message=
"All IMP classes should have CamelCase names. The following do not: %s." \
860 self.assertEqual(len(bad), 0, message)
862 def _check_function_name(self, prefix, name, verbs, all, exceptions, words,
865 fullname=prefix+
"."+name
868 old_exceptions=[
'unprotected_evaluate',
"unprotected_evaluate_if_good",
869 "unprotected_evaluate_if_below",
870 "after_evaluate",
"before_evaluate",
"has_attribute",
871 "decorate_particle",
"particle_is_instance"]
872 if name
in old_exceptions:
875 if fullname
in exceptions:
877 if name.endswith(
"swigregister"):
879 if name.lower() != name:
880 if name[0].lower() != name[0]
and name.split(
'_')[0]
in all:
885 tokens= name.split(
"_")
886 if tokens[0]
not in verbs:
889 if not self._check_spelling(t, words):
891 print(
"misspelled %s in %s" % (t, name))
895 def _static_method(self, module, prefix, name):
896 """For static methods of the form Foo.bar SWIG creates free functions
897 named Foo_bar. Exclude these from spelling checks since the method
898 Foo.bar has already been checked."""
899 if prefix
is None and '_' in name:
900 modobj = eval(module)
901 cls, meth = name.split(
'_', 1)
902 if hasattr(modobj, cls):
903 clsobj = eval(module +
'.' + cls)
904 if hasattr(clsobj, meth):
907 def _check_function_names(self, module, prefix, names, verbs, all,
908 exceptions, words, misspelled):
911 typ = self._get_type(module, name)
912 if name.startswith(
"_")
or name ==
"weakref_proxy":
914 if typ
in (types.BuiltinMethodType, types.MethodType) \
915 or (typ == types.FunctionType
and \
916 not self._static_method(module, prefix, name)):
917 bad.extend(self._check_function_name(prefix, name, verbs, all,
920 if typ == type
and "SwigPyIterator" not in name:
921 members=eval(
"dir("+module+
"."+name+
")")
922 bad.extend(self._check_function_names(module+
"."+name,
923 name, members, verbs, [],
929 """Check that all the functions in the module follow the IMP
930 naming conventions."""
932 verbs=set([
"add",
"remove",
"get",
"set",
"evaluate",
"compute",
"show",
"create",
"destroy",
933 "push",
"pop",
"write",
"read",
"do",
"show",
"load",
"save",
"reset",
935 "clear",
"handle",
"update",
"apply",
"optimize",
"reserve",
"dump",
936 "propose",
"setup",
"teardown",
"visit",
"find",
"run",
"swap",
"link",
939 bad=self._check_function_names(module.__name__,
None, all, verbs, all, exceptions, words, misspelled)
940 message=
"All IMP methods and functions should have lower case names separated by underscores and beginning with a verb, preferably one of ['add', 'remove', 'get', 'set', 'create', 'destroy']. Each of the words should be a properly spelled English word. The following do not (given our limited list of verbs that we check for):\n%(bad)s\nIf there is a good reason for them not to (eg it does start with a verb, just one with a meaning that is not covered by the normal list), add them to the function_name_exceptions variable in the standards_exceptions file. Otherwise, please fix. The current verb list is %(verbs)s" \
941 % {
"bad":
"\n".join(bad),
"verbs":verbs}
942 if len(misspelled) > 0:
943 message +=
"\nMisspelled words: " +
", ".join(set(misspelled)) \
944 +
". Add words to the spelling_exceptions variable " \
945 +
"of the standards_exceptions file if needed."
946 self.assertEqual(len(bad), 0, message)
950 """Check that all the classes in modulename have a show method"""
958 if not eval(
'hasattr(%s.%s, "__swig_destroy__")' \
959 % (modulename.__name__, f)):
961 if self._get_type(modulename.__name__, f) == type \
962 and not f.startswith(
"_") \
963 and not f.endswith(
"_swigregister")\
964 and f
not in exceptions\
965 and not f.endswith(
"Temp")
and not f.endswith(
"Iterator")\
966 and not f.endswith(
"Exception")
and\
967 f
not in modulename._raii_types
and \
968 f
not in modulename._plural_types:
969 if not hasattr(getattr(modulename, f),
'show'):
971 message=
"All IMP classes should support show and __str__. The following do not:\n%s\n If there is a good reason for them not to, add them to the show_exceptions variable in the IMPModuleTest call. Otherwise, please fix." \
972 %
"\n".join(not_found)
973 self.assertEqual(len(not_found), 0, message)
975 self.assertIn(e, all,
"Show exception "+e+
" is not a class in module")
976 self.assertTrue(
not hasattr(getattr(modulename, e),
'show'),
977 "Exception "+e+
" is not really a show exception")
980 """Run the named example script.
981 @return a dictionary of all the script's global variables.
982 This can be queried in a test case to make sure
983 the example performed correctly."""
988 path, name = os.path.split(filename)
989 oldsyspath = sys.path[:]
990 olssysargv= sys.argv[:]
991 sys.path.insert(0, path)
996 exec(open(filename).read(), vars)
999 except SystemExit
as e:
1000 if e.code != 0
and e.code
is not None:
1001 raise _FatalError(
"Example exit with code %s" % str(e.code))
1005 sys.path = oldsyspath
1006 sys.argv= olssysargv
1008 return _ExecDictProxy(vars)
1011 """Run a Python module as if with "python -m <modname>",
1012 with the given list of arguments as sys.argv.
1014 If module is an already-imported Python module, run its 'main'
1015 function and return the result.
1017 If module is a string, run the module in a subprocess and return
1018 a subprocess.Popen-like object containing the child stdin,
1021 def mock_setup_from_argv(*args, **kwargs):
1024 if type(module) == type(os):
1027 mod = __import__(module, {}, {}, [
''])
1028 modpath = mod.__file__
1029 if modpath.endswith(
'.pyc'):
1030 modpath = modpath[:-1]
1031 if type(module) == type(os):
1032 old_sys_argv = sys.argv
1034 old_setup = IMP.setup_from_argv
1035 IMP.setup_from_argv = mock_setup_from_argv
1037 sys.argv = [modpath] + args
1038 return module.main()
1040 IMP.setup_from_argv = old_setup
1041 sys.argv = old_sys_argv
1043 return _SubprocessWrapper(sys.executable, [modpath] + args)
1046 """Check a Python module designed to be runnable with 'python -m'
1047 to make sure it supports standard command line options."""
1050 out, err = r.communicate()
1051 self.assertEqual(r.returncode, 0)
1052 self.assertNotEqual(err,
"")
1053 self.assertEqual(out,
"")
1056 class _ExecDictProxy(object):
1057 """exec returns a Python dictionary, which contains IMP objects, other
1058 Python objects, as well as base Python modules (such as sys and
1059 __builtins__). If we just delete this dictionary, it is entirely
1060 possible that base Python modules are removed from the dictionary
1061 *before* some IMP objects. This will prevent the IMP objects' Python
1062 destructors from running properly, so C++ objects will not be
1063 cleaned up. This class proxies the base dict class, and on deletion
1064 attempts to remove keys from the dictionary in an order that allows
1065 IMP destructors to fire."""
1066 def __init__(self, d):
1070 module_type = type(IMP)
1073 if type(d[k]) != module_type:
1076 for meth
in [
'__contains__',
'__getitem__',
'__iter__',
'__len__',
1077 'get',
'has_key',
'items',
'keys',
'values']:
1078 exec(
"def %s(self, *args, **keys): "
1079 "return self._d.%s(*args, **keys)" % (meth, meth))
1082 class _TestResult(unittest.TextTestResult):
1084 def __init__(self, stream=None, descriptions=None, verbosity=None):
1085 super(_TestResult, self).__init__(stream, descriptions, verbosity)
1088 def stopTestRun(self):
1089 if 'IMP_TEST_DETAIL_DIR' in os.environ:
1090 fname = os.path.join(os.environ[
'IMP_TEST_DETAIL_DIR'],
1091 os.path.basename(sys.argv[0]))
1092 with open(fname,
'wb')
as fh:
1093 pickle.dump(self.all_tests, fh, -1)
1094 super(_TestResult, self).stopTestRun()
1096 def startTest(self, test):
1097 super(_TestResult, self).startTest(test)
1098 test.start_time=datetime.datetime.now()
1100 def _test_finished(self, test, state, detail=None):
1101 delta = datetime.datetime.now() - test.start_time
1103 pv= delta.total_seconds()
1104 except AttributeError:
1105 pv = (float(delta.microseconds) \
1106 + (delta.seconds + delta.days * 24 * 3600) * 10**6) / 10**6
1108 self.stream.write(
"in %.3fs ... " % pv)
1109 if detail
is not None and not isinstance(detail, str):
1110 detail = self._exc_info_to_string(detail, test)
1111 test_doc = self.getDescription(test)
1112 test_name = test.id()
1113 if test_name.startswith(
'__main__.'):
1114 test_name = test_name[9:]
1115 self.all_tests.append({
'name': test_name,
1116 'docstring': test_doc,
1117 'time': pv,
'state': state,
'detail': detail})
1119 def addSuccess(self, test):
1120 self._test_finished(test,
'OK')
1121 super(_TestResult, self).addSuccess(test)
1123 def addError(self, test, err):
1124 self._test_finished(test,
'ERROR', err)
1125 super(_TestResult, self).addError(test, err)
1127 def addFailure(self, test, err):
1128 self._test_finished(test,
'FAIL', err)
1129 super(_TestResult, self).addFailure(test, err)
1131 def addSkip(self, test, reason):
1132 self._test_finished(test,
'SKIP', reason)
1133 super(_TestResult, self).addSkip(test, reason)
1135 def addExpectedFailure(self, test, err):
1136 self._test_finished(test,
'EXPFAIL', err)
1137 super(_TestResult, self).addExpectedFailure(test, err)
1139 def addUnexpectedSuccess(self, test):
1140 self._test_finished(test,
'UNEXPSUC')
1141 super(_TestResult, self).addUnexpectedSuccess(test)
1143 def getDescription(self, test):
1144 doc_first_line = test.shortDescription()
1145 if self.descriptions
and doc_first_line:
1146 return doc_first_line
1151 class _TestRunner(unittest.TextTestRunner):
1152 def _makeResult(self):
1153 return _TestResult(self.stream, self.descriptions, self.verbosity)
1157 """Run a set of tests; similar to unittest.main().
1158 Obviates the need to separately import the 'unittest' module, and
1159 ensures that main() is from the same unittest module that the
1160 IMP.test testcases are. In addition, turns on some extra checks
1161 (e.g. trying to use deprecated code will cause an exception
1165 return unittest.main(testRunner=_TestRunner, *args, **keys)
1168 class _SubprocessWrapper(subprocess.Popen):
1169 def __init__(self, app, args):
1172 if sys.platform ==
'win32' and app != sys.executable:
1174 libdir = os.environ[
'PYTHONPATH'].split(
';')[0]
1175 env = os.environ.copy()
1176 env[
'PATH'] +=
';' + libdir
1179 subprocess.Popen.__init__(self, [app]+list(args),
1180 stdin=subprocess.PIPE,
1181 stdout=subprocess.PIPE,
1182 stderr=subprocess.PIPE, env=env,
1183 universal_newlines=
True)
1187 """Super class for simple IMP application test cases"""
1188 def _get_application_file_name(self, filename):
1191 if sys.platform ==
'win32':
1199 """Run an application with the given list of arguments.
1200 @return a subprocess.Popen-like object containing the child stdin,
1203 filename = self._get_application_file_name(app)
1204 if sys.platform ==
'win32':
1206 return _SubprocessWrapper(os.path.join(os.environ[
'IMP_BIN_DIR'],
1209 return _SubprocessWrapper(filename, args)
1212 """Run a Python application with the given list of arguments.
1213 The Python application should be self-runnable (i.e. it should
1214 be executable and with a #! on the first line).
1215 @return a subprocess.Popen-like object containing the child stdin,
1219 if sys.executable !=
'/usr/bin/python' and 'IMP_BIN_DIR' in os.environ:
1220 return _SubprocessWrapper(sys.executable,
1221 [os.path.join(os.environ[
'IMP_BIN_DIR'], app)] + args)
1223 return _SubprocessWrapper(app, args)
1226 """Import an installed Python application, rather than running it.
1227 This is useful to directly test components of the application.
1228 @return the Python module object."""
1230 import importlib.machinery
1234 name = os.path.splitext(app)[0]
1235 pathname = os.path.join(os.environ[
'IMP_BIN_DIR'], app)
1237 return importlib.machinery.SourceFileLoader(name,
1238 pathname).load_module()
1240 return imp.load_source(name, pathname)
1243 """Run an application with the given list of arguments.
1244 @return a subprocess.Popen-like object containing the child stdin,
1247 return _SubprocessWrapper(sys.executable, [app]+args)
1250 """Assert that the application exited cleanly (return value = 0)."""
1252 raise OSError(
"Application exited with signal %d\n" % -ret\
1255 self.assertEqual(ret, 0,
1256 "Application exited uncleanly, with exit code %d\n" % ret\
1260 """Read and return a set of shell commands from a doxygen file.
1261 Each command is assumed to be in a \code{.sh}...\endcode block.
1262 The doxygen file is specified relative to the test file itself.
1263 This is used to make sure the commands shown in an application
1264 example actually work (the testcase can also check the resulting
1265 files for correctness)."""
1266 def win32_normpath(p):
1269 return " ".join([os.path.normpath(x)
for x
in p.split()])
1270 def fix_win32_command(cmd):
1272 if cmd.startswith(
'cp -r '):
1273 return 'xcopy /E ' + win32_normpath(cmd[6:])
1274 elif cmd.startswith(
'cp '):
1275 return 'copy ' + win32_normpath(cmd[3:])
1278 d = os.path.dirname(sys.argv[0])
1279 doc = os.path.join(d, doxfile)
1283 with open(doc)
as fh:
1284 for line
in fh.readlines():
1285 if '\code{.sh}' in line:
1287 elif '\endcode' in line:
1290 cmds.append(line.rstrip(
'\r\n').replace(
1291 '<imp_example_path>', example_path))
1292 if sys.platform ==
'win32':
1293 cmds = [fix_win32_command(x)
for x
in cmds]
1297 "Print and run a shell command, as returned by read_shell_commands()"
1300 p = subprocess.call(cmd, shell=
True)
1302 raise OSError(
"%s failed with exit value %d" % (cmd, p))
1306 """Check to make sure the number of C++ object references is as expected"""
1308 def __init__(self, testcase):
1312 IMP._director_objects.cleanup()
1313 self.__testcase = testcase
1315 self.__basenum = IMP.Object.get_number_of_live_objects()
1319 "Make sure that the number of references matches the expected value."
1321 IMP._director_objects.cleanup()
1324 newnum=IMP.Object.get_number_of_live_objects()-self.__basenum
1325 t.assertEqual(newnum, expected,
1326 "Number of objects don't match: "\
1328 +
" != "+ str(expected) +
" found "+\
1334 """Check to make sure the number of director references is as expected"""
1336 def __init__(self, testcase):
1337 IMP._director_objects.cleanup()
1338 self.__testcase = testcase
1339 self.__basenum = IMP._director_objects.get_object_count()
1342 """Make sure that the number of references matches the expected value.
1343 If force_cleanup is set, clean up any unused references first before
1344 doing the assertion.
1348 IMP._director_objects.cleanup()
1349 t.assertEqual(IMP._director_objects.get_object_count() \
1350 - self.__basenum, expected)
1358 if sys.platform ==
'win32' and 'PYTHONPATH' in os.environ \
1359 and 'IMP_BIN_DIR' in os.environ:
1360 libdir = os.environ[
'PYTHONPATH'].split(
';')[0]
1361 bindir = os.environ[
'IMP_BIN_DIR']
1362 path = os.environ[
'PATH']
1363 if libdir
not in path
or bindir
not in path:
1364 os.environ[
'PATH'] = bindir +
';' + libdir +
';' + path
1367 def get_module_version():
1368 """get_module_version() -> std::string const"""
1369 return _IMP_test.get_module_version()
1372 """get_example_path(std::string fname) -> std::string"""
1373 return _IMP_test.get_example_path(fname)
1376 """get_data_path(std::string fname) -> std::string"""
1377 return _IMP_test.get_data_path(fname)
1379 from .
import _version_check
1380 _version_check.check_version(get_module_version())
1381 __version__ = get_module_version()
def run_python_module
Run a Python module as if with "python -m <modname>", with the given list of arguments as sys...
def temporary_working_directory
Simple context manager to run in a temporary directory.
def assertApplicationExitedCleanly
Assert that the application exited cleanly (return value = 0).
CheckLevel get_check_level()
Get the current audit mode.
def import_python_application
Import an installed Python application, rather than running it.
def open_input_file
Open and return an input file in the top-level test directory.
def run_application
Run an application with the given list of arguments.
def randomize_particles
Randomize the xyz coordinates of a list of particles.
A general exception for an internal error in IMP.
def main
Run a set of tests; similar to unittest.main().
An exception for an invalid usage of IMP.
Super class for simple IMP application test cases.
def assertRaisesInternalException
Assert that the given callable object raises InternalException.
std::string get_example_path(std::string file_name)
Return the full path to one of this module's example files.
def assert_number
Make sure that the number of references matches the expected value.
Check to make sure the number of director references is as expected.
def assertShow
Check that all the classes in modulename have a show method.
def run_shell_command
Print and run a shell command, as returned by read_shell_commands()
def assertRaisesUsageException
Assert that the given callable object raises UsageException.
Vector3D get_random_vector_in(const Cylinder3D &c)
Generate a random vector in a cylinder with uniform density.
def assertSequenceAlmostEqual
Fail if the difference between any two items in the two sequences are exceed the specified number of ...
Class for storing model, its restraints, constraints, and particles.
def run_python_application
Run a Python application with the given list of arguments.
def assert_number
Make sure that the number of references matches the expected value.
Simple RAII-style class to run in a temporary directory.
Strings get_live_object_names()
Return the names of all live objects.
def check_standard_object_methods
Check methods that every IMP::Object class should have.
def particle_distance
Return distance between two given particles.
def check_unary_function_deriv
Check the unary function func's derivatives against numerical approximations between lb and ub...
def get_tmp_file_name
Get the full name of an output file in the tmp directory.
Version and module information for Objects.
def run_example
Run the named example script.
def get_magnitude
Get the magnitude of a list of floats.
void set_deprecation_exceptions(bool tf)
Toggle whether an exception is thrown when a deprecated method is used.
def check_unary_function_min
Make sure that the minimum of the unary function func over the range between lb and ub is at expected...
def probabilistic_check
Help handle a test which is expected to fail some fraction of the time.
def create_particles_in_box
Create a bunch of particles in a box.
def deprecated_object
Python decorator to mark a class as deprecated.
General purpose algebraic and geometric methods that are expected to be used by a wide variety of IMP...
def assertNotImplemented
Assert that the given callable object is not implemented.
The general base class for IMP exceptions.
def numerical_derivative
Calculate the derivative of the single-value function func at point val.
std::string get_example_path(std::string file_name)
Return the full path to one of this module's example files.
def xyz_numerical_derivatives
Calculate the x,y and z derivatives of the scoring function sf on the xyz particle.
def failure_probability
Estimate how likely a given block of code is to raise an AssertionError.
def assertClassNames
Check that all the classes in the module follow the IMP naming conventions.
def create_point_particle
Make a particle with optimizable x, y and z attributes, and add it to the model.
Class to handle individual particles of a Model object.
def read_shell_commands
Read and return a set of shell commands from a doxygen file.
std::string get_data_path(std::string file_name)
Return the full path to one of this module's data files.
Check to make sure the number of C++ object references is as expected.
Simple RAII-style class to make a temporary directory.
def assertFunctionNames
Check that all the functions in the module follow the IMP naming conventions.
def assertValueObjects
Check that all the C++ classes in the module are values or objects.
Super class for IMP test cases.
def assertXYZDerivativesInTolerance
Assert that x,y,z analytical derivatives match numerical within a tolerance, or a percentage (of the ...
def temporary_directory
Simple context manager to make a temporary directory.
def run_script
Run an application with the given list of arguments.
def get_input_file_name
Get the full name of an input file in the top-level test directory.
def check_runnable_python_module
Check a Python module designed to be runnable with 'python -m' to make sure it supports standard comm...
void set_check_level(CheckLevel tf)
Control runtime checks in the code.