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_NUMPY = _IMP_test.IMP_KERNEL_HAS_NUMPY
239 IMP_KERNEL_HAS_GPERFTOOLS = _IMP_test.IMP_KERNEL_HAS_GPERFTOOLS
240 IMP_KERNEL_HAS_TCMALLOC_HEAPCHECKER = _IMP_test.IMP_KERNEL_HAS_TCMALLOC_HEAPCHECKER
241 IMP_KERNEL_HAS_TCMALLOC_HEAPPROFILER = _IMP_test.IMP_KERNEL_HAS_TCMALLOC_HEAPPROFILER
242 IMPKERNEL_SHOW_WARNINGS = _IMP_test.IMPKERNEL_SHOW_WARNINGS
245 class _DirectorObjects(object):
246 """@internal Simple class to keep references to director objects
247 to prevent premature deletion."""
250 def register(self, obj):
251 """Take a reference to a director object; will only work for
252 refcounted C++ classes"""
253 if hasattr(obj,
'get_ref_count'):
254 self._objects.append(obj)
256 """Only drop our reference and allow cleanup by Python if no other
257 Python references exist (we hold 3 references: one in self._objects,
258 one in x, and one in the argument list for getrefcount) *and* no
259 other C++ references exist (the Python object always holds one)"""
260 objs = [x
for x
in self._objects
if sys.getrefcount(x) > 3 \
261 or x.get_ref_count() > 1]
265 def get_object_count(self):
266 """Get number of director objects (useful for testing only)"""
267 return len(self._objects)
268 _director_objects = _DirectorObjects()
270 class _ostream(object):
271 """Proxy of C++ std::ostream class."""
273 thisown = _swig_property(
lambda x: x.this.own(),
lambda x, v: x.this.own(v), doc=
'The membership flag')
275 def __init__(self, *args, **kwargs):
276 raise AttributeError(
"No constructor defined")
277 __repr__ = _swig_repr
279 def write(self, osa_buf):
280 """write(_ostream self, char const * osa_buf)"""
281 return _IMP_test._ostream_write(self, osa_buf)
283 _ostream_swigregister = _IMP_test._ostream_swigregister
284 _ostream_swigregister(_ostream)
286 IMP_COMPILER_HAS_OVERRIDE = _IMP_test.IMP_COMPILER_HAS_OVERRIDE
287 IMP_COMPILER_HAS_FINAL = _IMP_test.IMP_COMPILER_HAS_FINAL
288 IMP_HAS_NOEXCEPT = _IMP_test.IMP_HAS_NOEXCEPT
289 IMP_C_OPEN_BINARY = _IMP_test.IMP_C_OPEN_BINARY
291 IMP_TEST_HAS_BOOST_FILESYSTEM = _IMP_test.IMP_TEST_HAS_BOOST_FILESYSTEM
292 IMP_TEST_HAS_BOOST_PROGRAMOPTIONS = _IMP_test.IMP_TEST_HAS_BOOST_PROGRAMOPTIONS
293 IMP_TEST_HAS_BOOST_RANDOM = _IMP_test.IMP_TEST_HAS_BOOST_RANDOM
294 IMP_TEST_HAS_BOOST_SYSTEM = _IMP_test.IMP_TEST_HAS_BOOST_SYSTEM
295 IMP_TEST_HAS_NUMPY = _IMP_test.IMP_TEST_HAS_NUMPY
296 IMPTEST_SHOW_WARNINGS = _IMP_test.IMPTEST_SHOW_WARNINGS
299 """@namespace IMP::test
300 @brief Methods and classes for testing the IMP kernel and modules.
316 from .
import _compat_python
317 from ._compat_python
import unittest2
318 from ._compat_python.unittest2.util
import safe_repr
335 def __load_unittest_package():
337 for modname, fromlist
in ((
'unittest', []),
341 u = __import__(modname, {}, {}, fromlist)
342 if hasattr(u,
'skip'):
345 errors.append(
"'%s' does not have the 'skip' decorator" \
347 except ImportError
as e:
348 errors.append(str(e))
350 return _compat_python.unittest2
351 raise ImportError(
"IMP.test requires a newer version of Python's unittest "
352 "package than is available. Either upgrade to a new "
353 "enough Python (at least 2.7 or 3.2) or install the "
354 "unittest2 package. Encountered errors: %s" \
356 unittest = __load_unittest_package()
359 expectedFailure = unittest.expectedFailure
361 skipIf = unittest.skipIf
362 skipUnless = unittest.skipUnless
364 class _TempDir(object):
365 def __init__(self, dir=None):
366 self.tmpdir = tempfile.mkdtemp(dir=dir)
368 shutil.rmtree(self.tmpdir, ignore_errors=
True)
370 @contextlib.contextmanager
372 """Simple context manager to run in a temporary directory.
373 While the context manager is active (within the 'with' block)
374 the current working directory is set to a temporary directory.
375 When the context manager exists, the working directory is reset
376 and the temporary directory deleted."""
377 origdir = os.getcwd()
378 tmpdir = tempfile.mkdtemp()
382 shutil.rmtree(tmpdir, ignore_errors=
True)
384 @contextlib.contextmanager
386 """Simple context manager to make a temporary directory.
387 The temporary directory has the same lifetime as the context manager
388 (i.e. it is created at the start of the 'with' block, and deleted
389 at the end of the block).
390 @param dir If given, the temporary directory is made as a subdirectory
391 of that directory, rather than in the default temporary
392 directory location (e.g. /tmp)
393 @return the full path to the temporary directory.
395 tmpdir = tempfile.mkdtemp(dir=dir)
397 shutil.rmtree(tmpdir, ignore_errors=
True)
400 """Calculate the derivative of the single-value function `func` at
401 point `val`. The derivative is calculated using simple finite
402 differences starting with the given `step`; Richardson extrapolation
403 is then used to extrapolate the derivative at step=0."""
408 f1 = func(val + step)
409 f2 = func(val - step)
411 d = [[(f1 - f2) / (2.0 * step)]]
413 for i
in range(1, maxsteps):
414 d.append([0.] * (i + 1))
416 f1 = func(val + step)
417 f2 = func(val - step)
418 d[i][0] = (f1 - f2) / (2.0 * step)
420 for j
in range(1, i + 1):
421 d[i][j] = (d[i][j-1] * fac - d[i-1][j-1]) / (fac - 1.)
423 errt = max(abs(d[i][j] - d[i][j-1]),
424 abs(d[i][j] - d[i-1][j-1]))
428 if abs(d[i][i] - d[i-1][i-1]) >= safe * err:
431 raise ValueError(
"Cannot calculate numerical derivative")
436 """Calculate the x,y and z derivatives of the scoring function `sf`
437 on the `xyz` particle. The derivatives are approximated numerically
438 using the numerical_derivatives() function."""
439 class _XYZDerivativeFunc(object):
440 def __init__(self, sf, xyz, basis_vector):
443 self._basis_vector = basis_vector
444 self._starting_coordinates = xyz.get_coordinates()
446 def __call__(self, val):
447 self._xyz.set_coordinates(self._starting_coordinates + \
448 self._basis_vector * val)
449 return self._sf.evaluate(
False)
453 for x
in ((1,0,0), (0,1,0), (0,0,1))])
457 """Super class for IMP test cases.
458 This provides a number of useful IMP-specific methods on top of
459 the standard Python `unittest.TestCase` class.
460 Test scripts should generally contain a subclass of this class,
461 conventionally called `Tests` (this makes it easier to run an
462 individual test from the command line) and use IMP::test::main()
463 as their main function."""
467 if not hasattr(unittest.TestCase,
'assertRegex'):
468 assertRegex = unittest.TestCase.assertRegexpMatches
469 assertNotRegex = unittest.TestCase.assertNotRegexpMatches
471 def __init__(self, *args, **keys):
472 unittest.TestCase.__init__(self, *args, **keys)
473 self._progname = os.path.abspath(sys.argv[0])
481 IMP.random_number_generator.seed(hash(time.time())%2**30)
487 if hasattr(self,
'_tmpdir'):
491 """Get the full name of an input file in the top-level
493 testdir = os.path.dirname(self._progname)
494 if self.__module__ !=
'__main__':
495 testdir = os.path.dirname(sys.modules[self.__module__].__file__)
496 dirs = testdir.split(os.path.sep)
497 for i
in range(len(dirs), 0, -1):
498 input = os.path.sep.join(dirs[:i] + [
'input'])
499 if os.path.isdir(input):
500 ret = os.path.join(input, filename)
501 if not os.path.exists(ret):
502 raise IOError(
"Test input file "+ret+
" does not exist")
504 raise IOError(
"No test input directory found")
507 """Open and return an input file in the top-level test directory."""
511 """Get the full name of an output file in the tmp directory.
512 The directory containing this file will be automatically
513 cleaned up when the test completes."""
514 if not hasattr(self,
'_tmpdir'):
515 self._tmpdir = _TempDir(os.environ.get(
'IMP_TMP_DIR'))
516 tmpdir = self._tmpdir.tmpdir
517 return os.path.join(tmpdir, filename)
520 """Get the magnitude of a list of floats"""
521 return sum([x*x
for x
in vector], 0)**.5
524 """Assert that the given callable object raises UsageException.
525 This differs from unittest's assertRaises in that the test
526 is skipped in fast mode (where usage checks are turned off)."""
531 """Assert that the given callable object raises InternalException.
532 This differs from unittest's assertRaises in that the test
533 is skipped in fast mode (where internal checks are turned off)."""
538 """Assert that the given callable object is not implemented."""
543 """Assert that x,y,z analytical derivatives match numerical within
544 a tolerance, or a percentage (of the analytical value), whichever
545 is larger. `sf` should be a ScoringFunction or Restraint,
546 although for backwards compatibility a Model is also accepted."""
548 derivs = xyz.get_derivatives()
550 pct = percentage / 100.0
551 self.assertAlmostEqual(self.
get_magnitude(derivs-num_derivs),0,
553 msg=
"Don't match "+str(derivs) + str(num_derivs))
554 self.assertAlmostEqual(derivs[0], num_derivs[0],
555 delta=max(tolerance, abs(derivs[0]) * pct))
556 self.assertAlmostEqual(derivs[1], num_derivs[1],
557 delta=max(tolerance, abs(derivs[1]) * pct))
558 self.assertAlmostEqual(derivs[2], num_derivs[2],
559 delta=max(tolerance, abs(derivs[2]) * pct))
563 """Fail if the difference between any two items in the two sequences
564 are exceed the specified number of places or delta. See
567 if delta
is not None and places
is not None:
568 raise TypeError(
"specify delta or places not both")
571 ftypename = ftype.__name__
573 stypename = stype.__name__
575 raise self.failureException(
576 'Sequences are of different types: %s != %s' % (
577 ftypename, stypename))
581 except (NotImplementedError, TypeError):
582 raise self.failureException(
583 'First %s has no length' % (ftypename))
586 except (NotImplementedError, TypeError):
587 raise self.failureException(
588 'Second %s has no length' % (stypename))
591 raise self.failureException(
592 'Sequences have non equal lengths: %d != %d' % (flen, slen))
595 for i
in range(min(flen, slen)):
596 differing =
'%ss differ: %s != %s\n' % (
597 ftypename.capitalize(), safe_repr(first),
602 except (TypeError, IndexError, NotImplementedError):
603 differing += (
'\nUnable to index element %d of first %s\n' %
609 except (TypeError, IndexError, NotImplementedError):
610 differing += (
'\nUnable to index element %d of second %s\n' %
615 self.assertAlmostEqual(
616 f, s, places=places, msg=msg, delta=delta)
617 except (TypeError, ValueError, NotImplementedError, AssertionError):
619 "\nFirst differing element "
620 "%d:\n%s\n%s\n") % (i, safe_repr(f), safe_repr(s))
625 standardMsg = differing
626 diffMsg =
'\n' +
'\n'.join(
627 difflib.ndiff(pprint.pformat(first).splitlines(),
628 pprint.pformat(second).splitlines()))
629 standardMsg = self._truncateMessage(standardMsg, diffMsg)
630 msg = self._formatMessage(msg, standardMsg)
631 raise self.failureException(msg)
634 """Make a particle with optimizable x, y and z attributes, and
635 add it to the model."""
643 """Help handle a test which is expected to fail some fraction of
644 the time. The test is run multiple times and an exception
645 is thrown only if it fails too many times.
646 @note Use of this function should be avoided. If there is a corner
647 case that results in a test 'occasionally' failing, write a
648 new test specifically for that corner case and assert that
649 it fails consistently (and remove the corner case from the
652 prob=chance_of_failure
656 prob= prob*chance_of_failure
657 for i
in range(0, tries):
665 raise AssertError(
"Too many failures")
668 """Estimate how likely a given block of code is to raise an
672 while failures < 10
and tries <1000:
678 return failures/tries
681 """Randomize the xyz coordinates of a list of particles"""
687 p.set_value(xkey, random.uniform(-deviation, deviation))
688 p.set_value(ykey, random.uniform(-deviation, deviation))
689 p.set_value(zkey, random.uniform(-deviation, deviation))
692 """Return distance between two given particles"""
696 dx = p1.get_value(xkey) - p2.get_value(xkey)
697 dy = p1.get_value(ykey) - p2.get_value(ykey)
698 dz = p1.get_value(zkey) - p2.get_value(zkey)
699 return math.sqrt(dx*dx + dy*dy + dz*dz)
702 """Check the unary function func's derivatives against numerical
703 approximations between lb and ub"""
704 for f
in [lb + i * step
for i
in range(1, int((ub-lb)/step))]:
705 (v,d)= func.evaluate_with_derivative(f)
707 self.assertAlmostEqual(d, da, delta=max(abs(.1 *d), 0.01))
710 """Make sure that the minimum of the unary function func over the
711 range between lb and ub is at expected_fmin"""
712 fmin, vmin = lb, func.evaluate(lb)
713 for f
in [lb + i * step
for i
in range(1, int((ub-lb)/step))]:
717 self.assertAlmostEqual(fmin, expected_fmin, delta=step)
720 """Check methods that every IMP::Object class should have"""
721 obj.set_was_used(
True)
724 self.assertIsNotNone(cls.get_from(obj))
725 self.assertRaises(ValueError, cls.get_from,
IMP.Model())
727 self.assertIsInstance(str(obj), str)
728 self.assertIsInstance(repr(obj), str)
730 verinf = obj.get_version_info()
739 """Create a bunch of particles in a box"""
744 for i
in range(0,num):
749 def _get_type(self, module, name):
750 return eval(
'type('+module+
"."+name+
')')
752 "Check that all the C++ classes in the module are values or objects."
754 ok = set(exceptions_list + module._value_types + module._object_types + module._raii_types + module._plural_types)
758 if self._get_type(module.__name__, name)==type
and not name.startswith(
"_"):
759 if name.find(
"SwigPyIterator") != -1:
762 if not eval(
'hasattr(%s.%s, "__swig_destroy__")' \
763 % (module.__name__, name)):
768 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." \
770 self.assertEqual(len(bad), 0, message)
771 for e
in exceptions_list:
772 self.assertTrue(e
not in module._value_types
773 + module._object_types
775 + module._plural_types,
776 "Value/Object exception "+e+
" is not an exception")
778 def _check_spelling(self, word, words):
779 """Check that the word is spelled correctly"""
780 if "words" not in dir(self):
782 wordlist= fh.read().split("\n")
784 custom_words=[
"info",
"prechange",
"int",
"ints",
"optimizeds",
"graphviz",
785 "voxel",
"voxels",
"endian",
'rna',
'dna',
786 "xyzr",
"pdbs",
"fft",
"ccc",
"gaussian"]
789 exclude_words = set([
"adapter",
"grey"])
790 self.words=set(wordlist+custom_words) - exclude_words
792 for i
in "0123456789":
797 if word
in self.words:
804 """Check that all the classes in the module follow the IMP
805 naming conventions."""
809 cc=re.compile(
"([A-Z][a-z]*)")
811 if self._get_type(module.__name__, name)==type
and not name.startswith(
"_"):
812 if name.find(
"SwigPyIterator") != -1:
814 for t
in re.findall(cc, name):
815 if not self._check_spelling(t.lower(), words):
816 misspelled.append(t.lower())
819 self.assertEqual(len(bad), 0,
820 "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." \
821 % (str(bad),
", ".join(set(misspelled))))
824 if self._get_type(module.__name__, name)==type
and not name.startswith(
"_"):
825 if name.find(
"SwigPyIterator") != -1:
827 if name.find(
'_') != -1:
829 if name.lower== name:
831 for t
in re.findall(cc, name):
832 if not self._check_spelling(t.lower(), words):
833 print(
"misspelled %s in %s" % (t, name))
835 message=
"All IMP classes should have CamelCase names. The following do not: %s." \
837 self.assertEqual(len(bad), 0, message)
839 def _check_function_name(self, prefix, name, verbs, all, exceptions, words,
842 fullname=prefix+
"."+name
845 old_exceptions=[
'unprotected_evaluate',
"unprotected_evaluate_if_good",
846 "unprotected_evaluate_if_below",
847 "after_evaluate",
"before_evaluate",
"has_attribute",
848 "decorate_particle",
"particle_is_instance"]
849 if name
in old_exceptions:
852 if fullname
in exceptions:
854 if name.endswith(
"swigregister"):
856 if name.lower() != name:
857 if name[0].lower() != name[0]
and name.split(
'_')[0]
in all:
862 tokens= name.split(
"_")
863 if tokens[0]
not in verbs:
866 if not self._check_spelling(t, words):
868 print(
"misspelled %s in %s" % (t, name))
872 def _static_method(self, module, prefix, name):
873 """For static methods of the form Foo.bar SWIG creates free functions
874 named Foo_bar. Exclude these from spelling checks since the method
875 Foo.bar has already been checked."""
876 if prefix
is None and '_' in name:
877 modobj = eval(module)
878 cls, meth = name.split(
'_', 1)
879 if hasattr(modobj, cls):
880 clsobj = eval(module +
'.' + cls)
881 if hasattr(clsobj, meth):
884 def _check_function_names(self, module, prefix, names, verbs, all,
885 exceptions, words, misspelled):
888 typ = self._get_type(module, name)
889 if name.startswith(
"_")
or name ==
"weakref_proxy":
891 if typ
in (types.BuiltinMethodType, types.MethodType) \
892 or (typ == types.FunctionType
and \
893 not self._static_method(module, prefix, name)):
894 bad.extend(self._check_function_name(prefix, name, verbs, all,
897 if typ == type
and "SwigPyIterator" not in name:
898 members=eval(
"dir("+module+
"."+name+
")")
899 bad.extend(self._check_function_names(module+
"."+name,
900 name, members, verbs, [],
906 """Check that all the functions in the module follow the IMP
907 naming conventions."""
909 verbs=set([
"add",
"remove",
"get",
"set",
"evaluate",
"compute",
"show",
"create",
"destroy",
910 "push",
"pop",
"write",
"read",
"do",
"show",
"load",
"save",
"reset",
912 "clear",
"handle",
"update",
"apply",
"optimize",
"reserve",
"dump",
913 "propose",
"setup",
"teardown",
"visit",
"find",
"run",
"swap",
"link",
916 bad=self._check_function_names(module.__name__,
None, all, verbs, all, exceptions, words, misspelled)
917 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" \
918 % {
"bad":
"\n".join(bad),
"verbs":verbs}
919 if len(misspelled) > 0:
920 message +=
"\nMisspelled words: " +
", ".join(set(misspelled)) \
921 +
". Add words to the spelling_exceptions variable " \
922 +
"of the standards_exceptions file if needed."
923 self.assertEqual(len(bad), 0, message)
927 """Check that all the classes in modulename have a show method"""
935 if not eval(
'hasattr(%s.%s, "__swig_destroy__")' \
936 % (modulename.__name__, f)):
938 if self._get_type(modulename.__name__, f) == type \
939 and not f.startswith(
"_") \
940 and not f.endswith(
"_swigregister")\
941 and f
not in exceptions\
942 and not f.endswith(
"Temp")
and not f.endswith(
"Iterator")\
943 and not f.endswith(
"Exception")
and\
944 f
not in modulename._raii_types
and \
945 f
not in modulename._plural_types:
946 if not hasattr(getattr(modulename, f),
'show'):
948 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." \
949 %
"\n".join(not_found)
950 self.assertEqual(len(not_found), 0, message)
952 self.assertIn(e, all,
"Show exception "+e+
" is not a class in module")
953 self.assertTrue(
not hasattr(getattr(modulename, e),
'show'),
954 "Exception "+e+
" is not really a show exception")
957 """Run the named example script.
958 @return a dictionary of all the script's global variables.
959 This can be queried in a test case to make sure
960 the example performed correctly."""
965 path, name = os.path.split(filename)
966 oldsyspath = sys.path[:]
967 olssysargv= sys.argv[:]
968 sys.path.insert(0, path)
973 exec(open(filename).read(), vars)
976 except SystemExit
as e:
977 if e.code != 0
and e.code
is not None:
978 raise _FatalError(
"Example exit with code %s" % str(e.code))
982 sys.path = oldsyspath
985 return _ExecDictProxy(vars)
988 """Run a Python module as if with "python -m <modname>",
989 with the given list of arguments as sys.argv.
991 If module is an already-imported Python module, run its 'main'
992 function and return the result.
994 If module is a string, run the module in a subprocess and return
995 a subprocess.Popen-like object containing the child stdin,
998 def mock_setup_from_argv(*args, **kwargs):
1001 if type(module) == type(os):
1004 mod = __import__(module, {}, {}, [
''])
1005 modpath = mod.__file__
1006 if modpath.endswith(
'.pyc'):
1007 modpath = modpath[:-1]
1008 if type(module) == type(os):
1009 old_sys_argv = sys.argv
1011 old_setup = IMP.setup_from_argv
1012 IMP.setup_from_argv = mock_setup_from_argv
1014 sys.argv = [modpath] + args
1015 return module.main()
1017 IMP.setup_from_argv = old_setup
1018 sys.argv = old_sys_argv
1020 return _SubprocessWrapper(sys.executable, [modpath] + args)
1023 """Check a Python module designed to be runnable with 'python -m'
1024 to make sure it supports standard command line options."""
1027 out, err = r.communicate()
1028 self.assertEqual(r.returncode, 0)
1029 self.assertNotEqual(err,
"")
1030 self.assertEqual(out,
"")
1033 class _ExecDictProxy(object):
1034 """exec returns a Python dictionary, which contains IMP objects, other
1035 Python objects, as well as base Python modules (such as sys and
1036 __builtins__). If we just delete this dictionary, it is entirely
1037 possible that base Python modules are removed from the dictionary
1038 *before* some IMP objects. This will prevent the IMP objects' Python
1039 destructors from running properly, so C++ objects will not be
1040 cleaned up. This class proxies the base dict class, and on deletion
1041 attempts to remove keys from the dictionary in an order that allows
1042 IMP destructors to fire."""
1043 def __init__(self, d):
1047 module_type = type(IMP)
1050 if type(d[k]) != module_type:
1053 for meth
in [
'__contains__',
'__getitem__',
'__iter__',
'__len__',
1054 'get',
'has_key',
'items',
'keys',
'values']:
1055 exec(
"def %s(self, *args, **keys): "
1056 "return self._d.%s(*args, **keys)" % (meth, meth))
1059 class _TestResult(unittest.TextTestResult):
1061 def __init__(self, stream=None, descriptions=None, verbosity=None):
1062 super(_TestResult, self).__init__(stream, descriptions, verbosity)
1065 def stopTestRun(self):
1066 if 'IMP_TEST_DETAIL_DIR' in os.environ:
1067 fname = os.path.join(os.environ[
'IMP_TEST_DETAIL_DIR'],
1068 os.path.basename(sys.argv[0]))
1069 with open(fname,
'wb')
as fh:
1070 pickle.dump(self.all_tests, fh, -1)
1071 super(_TestResult, self).stopTestRun()
1073 def startTest(self, test):
1074 super(_TestResult, self).startTest(test)
1075 test.start_time=datetime.datetime.now()
1077 def _test_finished(self, test, state, detail=None):
1078 delta = datetime.datetime.now() - test.start_time
1080 pv= delta.total_seconds()
1081 except AttributeError:
1082 pv = (float(delta.microseconds) \
1083 + (delta.seconds + delta.days * 24 * 3600) * 10**6) / 10**6
1085 self.stream.write(
"in %.3fs ... " % pv)
1086 if detail
is not None and not isinstance(detail, str):
1087 detail = self._exc_info_to_string(detail, test)
1088 test_doc = self.getDescription(test)
1089 test_name = test.id()
1090 if test_name.startswith(
'__main__.'):
1091 test_name = test_name[9:]
1092 self.all_tests.append({
'name': test_name,
1093 'docstring': test_doc,
1094 'time': pv,
'state': state,
'detail': detail})
1096 def addSuccess(self, test):
1097 self._test_finished(test,
'OK')
1098 super(_TestResult, self).addSuccess(test)
1100 def addError(self, test, err):
1101 self._test_finished(test,
'ERROR', err)
1102 super(_TestResult, self).addError(test, err)
1104 def addFailure(self, test, err):
1105 self._test_finished(test,
'FAIL', err)
1106 super(_TestResult, self).addFailure(test, err)
1108 def addSkip(self, test, reason):
1109 self._test_finished(test,
'SKIP', reason)
1110 super(_TestResult, self).addSkip(test, reason)
1112 def addExpectedFailure(self, test, err):
1113 self._test_finished(test,
'EXPFAIL', err)
1114 super(_TestResult, self).addExpectedFailure(test, err)
1116 def addUnexpectedSuccess(self, test):
1117 self._test_finished(test,
'UNEXPSUC')
1118 super(_TestResult, self).addUnexpectedSuccess(test)
1120 def getDescription(self, test):
1121 doc_first_line = test.shortDescription()
1122 if self.descriptions
and doc_first_line:
1123 return doc_first_line
1128 class _TestRunner(unittest.TextTestRunner):
1129 def _makeResult(self):
1130 return _TestResult(self.stream, self.descriptions, self.verbosity)
1134 """Run a set of tests; similar to unittest.main().
1135 Obviates the need to separately import the 'unittest' module, and
1136 ensures that main() is from the same unittest module that the
1137 IMP.test testcases are. In addition, turns on some extra checks
1138 (e.g. trying to use deprecated code will cause an exception
1142 return unittest.main(testRunner=_TestRunner, *args, **keys)
1145 class _SubprocessWrapper(subprocess.Popen):
1146 def __init__(self, app, args, cwd=None):
1149 if sys.platform ==
'win32' and app != sys.executable:
1151 libdir = os.environ[
'PYTHONPATH'].split(
';')[0]
1152 env = os.environ.copy()
1153 env[
'PATH'] +=
';' + libdir
1156 subprocess.Popen.__init__(self, [app]+list(args),
1157 stdin=subprocess.PIPE,
1158 stdout=subprocess.PIPE,
1159 stderr=subprocess.PIPE, env=env, cwd=cwd,
1160 universal_newlines=
True)
1164 """Super class for simple IMP application test cases"""
1165 def _get_application_file_name(self, filename):
1168 if sys.platform ==
'win32':
1176 """Run an application with the given list of arguments.
1177 @return a subprocess.Popen-like object containing the child stdin,
1180 filename = self._get_application_file_name(app)
1181 if sys.platform ==
'win32':
1183 return _SubprocessWrapper(os.path.join(os.environ[
'IMP_BIN_DIR'],
1184 filename), args, cwd=cwd)
1186 return _SubprocessWrapper(filename, args, cwd=cwd)
1189 """Run a Python application with the given list of arguments.
1190 The Python application should be self-runnable (i.e. it should
1191 be executable and with a #! on the first line).
1192 @return a subprocess.Popen-like object containing the child stdin,
1196 if sys.executable !=
'/usr/bin/python' and 'IMP_BIN_DIR' in os.environ:
1197 return _SubprocessWrapper(sys.executable,
1198 [os.path.join(os.environ[
'IMP_BIN_DIR'], app)] + args)
1200 return _SubprocessWrapper(app, args)
1203 """Import an installed Python application, rather than running it.
1204 This is useful to directly test components of the application.
1205 @return the Python module object."""
1207 import importlib.machinery
1211 name = os.path.splitext(app)[0]
1212 pathname = os.path.join(os.environ[
'IMP_BIN_DIR'], app)
1214 return importlib.machinery.SourceFileLoader(name,
1215 pathname).load_module()
1217 return imp.load_source(name, pathname)
1220 """Run an application with the given list of arguments.
1221 @return a subprocess.Popen-like object containing the child stdin,
1224 return _SubprocessWrapper(sys.executable, [app]+args)
1227 """Assert that the application exited cleanly (return value = 0)."""
1229 raise OSError(
"Application exited with signal %d\n" % -ret\
1232 self.assertEqual(ret, 0,
1233 "Application exited uncleanly, with exit code %d\n" % ret\
1237 """Read and return a set of shell commands from a doxygen file.
1238 Each command is assumed to be in a \code{.sh}...\endcode block.
1239 The doxygen file is specified relative to the test file itself.
1240 This is used to make sure the commands shown in an application
1241 example actually work (the testcase can also check the resulting
1242 files for correctness)."""
1243 def win32_normpath(p):
1246 return " ".join([os.path.normpath(x)
for x
in p.split()])
1247 def fix_win32_command(cmd):
1249 if cmd.startswith(
'cp -r '):
1250 return 'xcopy /E ' + win32_normpath(cmd[6:])
1251 elif cmd.startswith(
'cp '):
1252 return 'copy ' + win32_normpath(cmd[3:])
1255 d = os.path.dirname(sys.argv[0])
1256 doc = os.path.join(d, doxfile)
1260 with open(doc)
as fh:
1261 for line
in fh.readlines():
1262 if '\code{.sh}' in line:
1264 elif '\endcode' in line:
1267 cmds.append(line.rstrip(
'\r\n').replace(
1268 '<imp_example_path>', example_path))
1269 if sys.platform ==
'win32':
1270 cmds = [fix_win32_command(x)
for x
in cmds]
1274 "Print and run a shell command, as returned by read_shell_commands()"
1277 p = subprocess.call(cmd, shell=
True)
1279 raise OSError(
"%s failed with exit value %d" % (cmd, p))
1283 """Check to make sure the number of C++ object references is as expected"""
1285 def __init__(self, testcase):
1289 IMP._director_objects.cleanup()
1290 self.__testcase = testcase
1292 self.__basenum = IMP.Object.get_number_of_live_objects()
1296 "Make sure that the number of references matches the expected value."
1298 IMP._director_objects.cleanup()
1301 newnum=IMP.Object.get_number_of_live_objects()-self.__basenum
1302 t.assertEqual(newnum, expected,
1303 "Number of objects don't match: "\
1305 +
" != "+ str(expected) +
" found "+\
1311 """Check to make sure the number of director references is as expected"""
1313 def __init__(self, testcase):
1314 IMP._director_objects.cleanup()
1315 self.__testcase = testcase
1316 self.__basenum = IMP._director_objects.get_object_count()
1319 """Make sure that the number of references matches the expected value.
1320 If force_cleanup is set, clean up any unused references first before
1321 doing the assertion.
1325 IMP._director_objects.cleanup()
1326 t.assertEqual(IMP._director_objects.get_object_count() \
1327 - self.__basenum, expected)
1335 if sys.platform ==
'win32' and 'PYTHONPATH' in os.environ \
1336 and 'IMP_BIN_DIR' in os.environ:
1337 libdir = os.environ[
'PYTHONPATH'].split(
';')[0]
1338 bindir = os.environ[
'IMP_BIN_DIR']
1339 path = os.environ[
'PATH']
1340 if libdir
not in path
or bindir
not in path:
1341 os.environ[
'PATH'] = bindir +
';' + libdir +
';' + path
1344 def get_module_version():
1345 """get_module_version() -> std::string const"""
1346 return _IMP_test.get_module_version()
1349 """get_example_path(std::string fname) -> std::string"""
1350 return _IMP_test.get_example_path(fname)
1353 """get_data_path(std::string fname) -> std::string"""
1354 return _IMP_test.get_data_path(fname)
1356 from .
import _version_check
1357 _version_check.check_version(get_module_version())
1358 __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.
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.
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.
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.