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
289 IMP_TEST_HAS_BOOST_FILESYSTEM = _IMP_test.IMP_TEST_HAS_BOOST_FILESYSTEM
290 IMP_TEST_HAS_BOOST_PROGRAMOPTIONS = _IMP_test.IMP_TEST_HAS_BOOST_PROGRAMOPTIONS
291 IMP_TEST_HAS_BOOST_RANDOM = _IMP_test.IMP_TEST_HAS_BOOST_RANDOM
292 IMP_TEST_HAS_BOOST_SYSTEM = _IMP_test.IMP_TEST_HAS_BOOST_SYSTEM
293 IMPTEST_SHOW_WARNINGS = _IMP_test.IMPTEST_SHOW_WARNINGS
296 """@namespace IMP::test
297 @brief Methods and classes for testing the IMP kernel and modules.
311 from .
import _compat_python
312 from ._compat_python
import unittest2
329 def __load_unittest_package():
331 for modname, fromlist
in ((
'unittest', []),
335 u = __import__(modname, {}, {}, fromlist)
336 if hasattr(u,
'skip'):
339 errors.append(
"'%s' does not have the 'skip' decorator" \
341 except ImportError
as e:
342 errors.append(str(e))
344 return _compat_python.unittest2
345 raise ImportError(
"IMP.test requires a newer version of Python's unittest "
346 "package than is available. Either upgrade to a new "
347 "enough Python (at least 2.7 or 3.2) or install the "
348 "unittest2 package. Encountered errors: %s" \
350 unittest = __load_unittest_package()
353 expectedFailure = unittest.expectedFailure
355 skipIf = unittest.skipIf
356 skipUnless = unittest.skipUnless
360 """Simple RAII-style class to run in a temporary directory.
361 When the object is created, the temporary directory is created
362 and becomes the current working directory. When the object goes out
363 of scope, the working directory is reset and the temporary directory
366 self.origdir = os.getcwd()
367 self.tmpdir = tempfile.mkdtemp()
368 os.chdir(self.tmpdir)
370 os.chdir(self.origdir)
371 shutil.rmtree(self.tmpdir, ignore_errors=
True)
373 @contextlib.contextmanager
375 """Simple context manager to run in a temporary directory.
376 While the context manager is active (within the 'with' block)
377 the current working directory is set to a temporary directory.
378 When the context manager exists, the working directory is reset
379 and the temporary directory deleted."""
380 origdir = os.getcwd()
381 tmpdir = tempfile.mkdtemp()
385 shutil.rmtree(tmpdir, ignore_errors=
True)
389 """Simple RAII-style class to make a temporary directory. When the object
390 is created, the temporary directory is created. When the object goes
391 out of scope, the temporary directory is deleted."""
392 def __init__(self, dir=None):
393 self.tmpdir = tempfile.mkdtemp(dir=dir)
395 shutil.rmtree(self.tmpdir, ignore_errors=
True)
397 class _TempDir(object):
398 def __init__(self, dir=None):
399 self.tmpdir = tempfile.mkdtemp(dir=dir)
401 shutil.rmtree(self.tmpdir, ignore_errors=
True)
403 @contextlib.contextmanager
405 """Simple context manager to make a temporary directory.
406 The temporary directory has the same lifetime as the context manager
407 (i.e. it is created at the start of the 'with' block, and deleted
408 at the end of the block).
409 @param dir If given, the temporary directory is made as a subdirectory
410 of that directory, rather than in the default temporary
411 directory location (e.g. /tmp)
412 @return the full path to the temporary directory.
414 tmpdir = tempfile.mkdtemp(dir=dir)
416 shutil.rmtree(tmpdir, ignore_errors=
True)
419 """Calculate the derivative of the single-value function `func` at
420 point `val`. The derivative is calculated using simple finite
421 differences starting with the given `step`; Richardson extrapolation
422 is then used to extrapolate the derivative at step=0."""
427 f1 = func(val + step)
428 f2 = func(val - step)
430 d = [[(f1 - f2) / (2.0 * step)]]
432 for i
in range(1, maxsteps):
433 d.append([0.] * (i + 1))
435 f1 = func(val + step)
436 f2 = func(val - step)
437 d[i][0] = (f1 - f2) / (2.0 * step)
439 for j
in range(1, i + 1):
440 d[i][j] = (d[i][j-1] * fac - d[i-1][j-1]) / (fac - 1.)
442 errt = max(abs(d[i][j] - d[i][j-1]),
443 abs(d[i][j] - d[i-1][j-1]))
447 if abs(d[i][i] - d[i-1][i-1]) >= safe * err:
450 raise ValueError(
"Cannot calculate numerical derivative")
455 """Calculate the x,y and z derivatives of the scoring function `sf`
456 on the `xyz` particle. The derivatives are approximated numerically
457 using the numerical_derivatives() function."""
458 class _XYZDerivativeFunc(object):
459 def __init__(self, sf, xyz, basis_vector):
462 self._basis_vector = basis_vector
463 self._starting_coordinates = xyz.get_coordinates()
465 def __call__(self, val):
466 self._xyz.set_coordinates(self._starting_coordinates + \
467 self._basis_vector * val)
468 return self._sf.evaluate(
False)
472 for x
in ((1,0,0), (0,1,0), (0,0,1))])
476 """Super class for IMP test cases.
477 This provides a number of useful IMP-specific methods on top of
478 the standard Python `unittest.TestCase` class.
479 Test scripts should generally contain a subclass of this class,
480 conventionally called `Tests` (this makes it easier to run an
481 individual test from the commane line) and use IMP::test::main()
482 as their main function."""
484 def __init__(self, *args, **keys):
485 unittest.TestCase.__init__(self, *args, **keys)
486 self._progname = os.path.abspath(sys.argv[0])
494 IMP.random_number_generator.seed(hash(time.time())%2**30)
500 if hasattr(self,
'_tmpdir'):
504 """Get the full name of an input file in the top-level
506 testdir = os.path.dirname(self._progname)
507 dirs = testdir.split(os.path.sep)
508 for i
in range(len(dirs), 0, -1):
509 input = os.path.sep.join(dirs[:i] + [
'input'])
510 if os.path.isdir(input):
511 ret = os.path.join(input, filename)
512 if not os.path.exists(ret):
513 raise IOError(
"Test input file "+ret+
" does not exist")
515 raise IOError(
"No test input directory found")
518 """Open and return an input file in the top-level test directory."""
522 """Get the full name of an output file in the tmp directory.
523 The directory containing this file will be automatically
524 cleaned up when the test completes."""
525 if not hasattr(self,
'_tmpdir'):
526 self._tmpdir = _TempDir(os.environ[
'IMP_TMP_DIR'])
527 tmpdir = self._tmpdir.tmpdir
528 return os.path.join(tmpdir, filename)
531 """Get the magnitude of a list of floats"""
532 return sum([x*x
for x
in vector], 0)**.5
535 """Assert that the given callable object raises UsageException.
536 This differs from unittest's assertRaises in that the test
537 is skipped in fast mode (where usage checks are turned off)."""
542 """Assert that the given callable object raises InternalException.
543 This differs from unittest's assertRaises in that the test
544 is skipped in fast mode (where internal checks are turned off)."""
549 """Assert that the given callable object is not implemented."""
554 """Assert that x,y,z analytical derivatives match numerical within
555 a tolerance, or a percentage (of the analytical value), whichever
556 is larger. `sf` should be a ScoringFunction or Restraint,
557 although for backwards compatibility a Model is also accepted."""
559 derivs = xyz.get_derivatives()
561 pct = percentage / 100.0
562 self.assertAlmostEqual(self.
get_magnitude(derivs-num_derivs),0,
564 msg=
"Don't match "+str(derivs) + str(num_derivs))
565 self.assertAlmostEqual(derivs[0], num_derivs[0],
566 delta=max(tolerance, abs(derivs[0]) * pct))
567 self.assertAlmostEqual(derivs[1], num_derivs[1],
568 delta=max(tolerance, abs(derivs[1]) * pct))
569 self.assertAlmostEqual(derivs[2], num_derivs[2],
570 delta=max(tolerance, abs(derivs[2]) * pct))
573 """Make a particle with optimizable x, y and z attributes, and
574 add it to the model."""
582 """Help handle a test which is expected to fail some fraction of
583 the time. The test is run multiple times and an exception
584 is thrown only if it fails too many times.
585 @note Use of this function should be avoided. If there is a corner
586 case that results in a test 'occasionally' failing, write a
587 new test specifically for that corner case and assert that
588 it fails consistently (and remove the corner case from the
591 prob=chance_of_failure
595 prob= prob*chance_of_failure
596 for i
in range(0, tries):
604 raise AssertError(
"Too many failures")
607 """Estimate how likely a given block of code is to raise an
611 while failures < 10
and tries <1000:
617 return failures/tries
620 """Randomize the xyz coordinates of a list of particles"""
626 p.set_value(xkey, random.uniform(-deviation, deviation))
627 p.set_value(ykey, random.uniform(-deviation, deviation))
628 p.set_value(zkey, random.uniform(-deviation, deviation))
631 """Return distance between two given particles"""
635 dx = p1.get_value(xkey) - p2.get_value(xkey)
636 dy = p1.get_value(ykey) - p2.get_value(ykey)
637 dz = p1.get_value(zkey) - p2.get_value(zkey)
638 return math.sqrt(dx*dx + dy*dy + dz*dz)
641 """Check the unary function func's derivatives against numerical
642 approximations between lb and ub"""
643 for f
in [lb + i * step
for i
in range(1, int((ub-lb)/step))]:
644 (v,d)= func.evaluate_with_derivative(f)
646 self.assertAlmostEqual(d, da, delta=max(abs(.1 *d), 0.01))
649 """Make sure that the minimum of the unary function func over the
650 range between lb and ub is at expected_fmin"""
651 fmin, vmin = lb, func.evaluate(lb)
652 for f
in [lb + i * step
for i
in range(1, int((ub-lb)/step))]:
656 self.assertAlmostEqual(fmin, expected_fmin, delta=step)
659 """Check that the get_from() static method works correctly"""
661 self.assertIsNotNone(cls.get_from(obj))
662 self.assertRaises(ValueError, cls.get_from,
IMP.Model())
667 """Create a bunch of particles in a box"""
672 for i
in range(0,num):
677 def _get_type(self, module, name):
678 return eval(
'type('+module+
"."+name+
')')
680 "Check that all the C++ classes in the module are values or objects."
682 ok = set(exceptions_list + module._value_types + module._object_types + module._raii_types + module._plural_types)
686 if self._get_type(module.__name__, name)==type
and not name.startswith(
"_"):
687 if name.find(
"SwigPyIterator") != -1:
690 if not eval(
'hasattr(%s.%s, "__swig_destroy__")' \
691 % (module.__name__, name)):
696 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." \
698 self.assertEqual(len(bad), 0, message)
699 for e
in exceptions_list:
700 self.assertTrue(e
not in module._value_types
701 + module._object_types
703 + module._plural_types,
704 "Value/Object exception "+e+
" is not an exception")
706 def _check_spelling(self, word, words):
707 """Check that the word is spelled correctly"""
708 if "words" not in dir(self):
710 wordlist= fh.read().split("\n")
712 custom_words=[
"info",
"prechange",
"int",
"ints",
"optimizeds",
"graphviz",
713 "voxel",
"voxels",
"endian",
'rna',
'dna',
714 "xyzr",
"pdbs",
"fft",
"ccc",
"gaussian"]
717 exclude_words = set([
"adapter",
"grey"])
718 self.words=set(wordlist+custom_words) - exclude_words
720 for i
in "0123456789":
725 if word
in self.words:
732 """Check that all the classes in the module follow the IMP
733 naming conventions."""
737 cc=re.compile(
"([A-Z][a-z]*)")
739 if self._get_type(module.__name__, name)==type
and not name.startswith(
"_"):
740 if name.find(
"SwigPyIterator") != -1:
742 for t
in re.findall(cc, name):
743 if not self._check_spelling(t.lower(), words):
744 misspelled.append(t.lower())
747 self.assertEqual(len(bad), 0,
748 "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." \
749 % (str(bad),
", ".join(set(misspelled))))
752 if self._get_type(module.__name__, name)==type
and not name.startswith(
"_"):
753 if name.find(
"SwigPyIterator") != -1:
755 if name.find(
'_') != -1:
757 if name.lower== name:
759 for t
in re.findall(cc, name):
760 if not self._check_spelling(t.lower(), words):
761 print(
"misspelled %s in %s" % (t, name))
763 message=
"All IMP classes should have CamelCase names. The following do not: %s." \
765 self.assertEqual(len(bad), 0, message)
767 def _check_function_name(self, prefix, name, verbs, all, exceptions, words,
770 fullname=prefix+
"."+name
773 old_exceptions=[
'unprotected_evaluate',
"unprotected_evaluate_if_good",
774 "unprotected_evaluate_if_below",
775 "after_evaluate",
"before_evaluate",
"has_attribute",
776 "decorate_particle",
"particle_is_instance"]
777 if name
in old_exceptions:
780 if fullname
in exceptions:
782 if name.endswith(
"swigregister"):
784 if name.lower() != name:
785 if name[0].lower() != name[0]
and name.split(
'_')[0]
in all:
790 tokens= name.split(
"_")
791 if tokens[0]
not in verbs:
794 if not self._check_spelling(t, words):
796 print(
"misspelled %s in %s" % (t, name))
800 def _static_method(self, module, prefix, name):
801 """For static methods of the form Foo.bar SWIG creates free functions
802 named Foo_bar. Exclude these from spelling checks since the method
803 Foo.bar has already been checked."""
804 if prefix
is None and '_' in name:
805 modobj = eval(module)
806 cls, meth = name.split(
'_', 1)
807 if hasattr(modobj, cls):
808 clsobj = eval(module +
'.' + cls)
809 if hasattr(clsobj, meth):
812 def _check_function_names(self, module, prefix, names, verbs, all,
813 exceptions, words, misspelled):
816 typ = self._get_type(module, name)
817 if name.startswith(
"_")
or name ==
"weakref_proxy":
819 if typ
in (types.BuiltinMethodType, types.MethodType) \
820 or (typ == types.FunctionType
and \
821 not self._static_method(module, prefix, name)):
822 bad.extend(self._check_function_name(prefix, name, verbs, all,
825 if typ == type
and "SwigPyIterator" not in name:
826 members=eval(
"dir("+module+
"."+name+
")")
827 bad.extend(self._check_function_names(module+
"."+name,
828 name, members, verbs, [],
834 """Check that all the functions in the module follow the IMP
835 naming conventions."""
837 verbs=set([
"add",
"remove",
"get",
"set",
"evaluate",
"compute",
"show",
"create",
"destroy",
838 "push",
"pop",
"write",
"read",
"do",
"show",
"load",
"save",
"reset",
840 "clear",
"handle",
"update",
"apply",
"optimize",
"reserve",
"dump",
841 "propose",
"setup",
"teardown",
"visit",
"find",
"run",
"swap",
"link",
844 bad=self._check_function_names(module.__name__,
None, all, verbs, all, exceptions, words, misspelled)
845 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" \
846 % {
"bad":
"\n".join(bad),
"verbs":verbs}
847 if len(misspelled) > 0:
848 message +=
"\nMisspelled words: " +
", ".join(set(misspelled)) \
849 +
". Add words to the spelling_exceptions variable " \
850 +
"of the standards_exceptions file if needed."
851 self.assertEqual(len(bad), 0, message)
855 """Check that all the classes in modulename have a show method"""
863 if not eval(
'hasattr(%s.%s, "__swig_destroy__")' \
864 % (modulename.__name__, f)):
866 if self._get_type(modulename.__name__, f) == type \
867 and not f.startswith(
"_") \
868 and not f.endswith(
"_swigregister")\
869 and f
not in exceptions\
870 and not f.endswith(
"Temp")
and not f.endswith(
"Iterator")\
871 and not f.endswith(
"Exception")
and\
872 f
not in modulename._raii_types
and \
873 f
not in modulename._plural_types:
874 if not hasattr(getattr(modulename, f),
'show'):
876 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." \
877 %
"\n".join(not_found)
878 self.assertEqual(len(not_found), 0, message)
880 self.assertIn(e, all,
"Show exception "+e+
" is not a class in module")
881 self.assertTrue(
not hasattr(getattr(modulename, e),
'show'),
882 "Exception "+e+
" is not really a show exception")
885 """Run the named example script.
886 @return a dictionary of all the script's global variables.
887 This can be queried in a test case to make sure
888 the example performed correctly."""
893 path, name = os.path.split(filename)
894 oldsyspath = sys.path[:]
895 olssysargv= sys.argv[:]
896 sys.path.insert(0, path)
901 exec(open(filename).read(), vars)
904 except SystemExit
as e:
905 if e.code != 0
and e.code
is not None:
906 raise _FatalError(
"Example exit with code %s" % str(e.code))
910 sys.path = oldsyspath
913 return _ExecDictProxy(vars)
916 """Run a Python module as if with "python -m <modname>",
917 with the given list of arguments as sys.argv.
919 If module is an already-imported Python module, run its 'main'
920 function and return the result.
922 If module is a string, run the module in a subprocess and return
923 a subprocess.Popen-like object containing the child stdin,
926 if type(module) == type(os):
929 mod = __import__(module, {}, {}, [
''])
930 modpath = mod.__file__
931 if modpath.endswith(
'.pyc'):
932 modpath = modpath[:-1]
933 if type(module) == type(os):
934 old_sys_argv = sys.argv
936 IMP.OptionParser._use_boost_parser =
False
938 sys.argv = [modpath] + args
941 IMP.OptionParser._use_boost_parser =
True
942 sys.argv = old_sys_argv
944 return _SubprocessWrapper(sys.executable, [modpath] + args)
947 """Check a Python module designed to be runnable with 'python -m'
948 to make sure it supports standard command line options."""
951 out, err = r.communicate()
952 self.assertEqual(r.returncode, 0)
953 self.assertNotEqual(err,
"")
954 self.assertEqual(out,
"")
957 class _ExecDictProxy(object):
958 """exec returns a Python dictionary, which contains IMP objects, other
959 Python objects, as well as base Python modules (such as sys and
960 __builtins__). If we just delete this dictionary, it is entirely
961 possible that base Python modules are removed from the dictionary
962 *before* some IMP objects. This will prevent the IMP objects' Python
963 destructors from running properly, so C++ objects will not be
964 cleaned up. This class proxies the base dict class, and on deletion
965 attempts to remove keys from the dictionary in an order that allows
966 IMP destructors to fire."""
967 def __init__(self, d):
971 module_type = type(IMP)
974 if type(d[k]) != module_type:
977 for meth
in [
'__contains__',
'__getitem__',
'__iter__',
'__len__',
978 'get',
'has_key',
'items',
'keys',
'values']:
979 exec(
"def %s(self, *args, **keys): "
980 "return self._d.%s(*args, **keys)" % (meth, meth))
983 class _TestResult(unittest.TextTestResult):
985 def __init__(self, stream=None, descriptions=None, verbosity=None):
986 super(_TestResult, self).__init__(stream, descriptions, verbosity)
989 def stopTestRun(self):
990 if 'IMP_TEST_DETAIL_DIR' in os.environ:
991 fname = os.path.join(os.environ[
'IMP_TEST_DETAIL_DIR'],
992 os.path.basename(sys.argv[0]))
993 with open(fname,
'wb')
as fh:
994 pickle.dump(self.all_tests, fh, -1)
995 super(_TestResult, self).stopTestRun()
997 def startTest(self, test):
998 super(_TestResult, self).startTest(test)
999 test.start_time=datetime.datetime.now()
1001 def _test_finished(self, test, state, detail=None):
1002 delta = datetime.datetime.now() - test.start_time
1004 pv= delta.total_seconds()
1005 except AttributeError:
1006 pv = (float(delta.microseconds) \
1007 + (delta.seconds + delta.days * 24 * 3600) * 10**6) / 10**6
1009 self.stream.write(
"in %.3fs ... " % pv)
1010 if detail
is not None and not isinstance(detail, str):
1011 detail = self._exc_info_to_string(detail, test)
1012 test_doc = self.getDescription(test)
1013 test_name = test.id()
1014 if test_name.startswith(
'__main__.'):
1015 test_name = test_name[9:]
1016 self.all_tests.append({
'name': test_name,
1017 'docstring': test_doc,
1018 'time': pv,
'state': state,
'detail': detail})
1020 def addSuccess(self, test):
1021 self._test_finished(test,
'OK')
1022 super(_TestResult, self).addSuccess(test)
1024 def addError(self, test, err):
1025 self._test_finished(test,
'ERROR', err)
1026 super(_TestResult, self).addError(test, err)
1028 def addFailure(self, test, err):
1029 self._test_finished(test,
'FAIL', err)
1030 super(_TestResult, self).addFailure(test, err)
1032 def addSkip(self, test, reason):
1033 self._test_finished(test,
'SKIP', reason)
1034 super(_TestResult, self).addSkip(test, reason)
1036 def addExpectedFailure(self, test, err):
1037 self._test_finished(test,
'EXPFAIL', err)
1038 super(_TestResult, self).addExpectedFailure(test, err)
1040 def addUnexpectedSuccess(self, test):
1041 self._test_finished(test,
'UNEXPSUC')
1042 super(_TestResult, self).addUnexpectedSuccess(test)
1044 def getDescription(self, test):
1045 doc_first_line = test.shortDescription()
1046 if self.descriptions
and doc_first_line:
1047 return doc_first_line
1052 class _TestRunner(unittest.TextTestRunner):
1053 def _makeResult(self):
1054 return _TestResult(self.stream, self.descriptions, self.verbosity)
1058 """Run a set of tests; similar to unittest.main().
1059 Obviates the need to separately import the 'unittest' module, and
1060 ensures that main() is from the same unittest module that the
1061 IMP.test testcases are. In addition, turns on some extra checks
1062 (e.g. trying to use deprecated code will cause an exception
1066 return unittest.main(testRunner=_TestRunner, *args, **keys)
1069 class _SubprocessWrapper(subprocess.Popen):
1070 def __init__(self, app, args):
1073 if sys.platform ==
'win32' and app != sys.executable:
1075 libdir = os.environ[
'PYTHONPATH'].split(
';')[0]
1076 env = os.environ.copy()
1077 env[
'PATH'] +=
';' + libdir
1080 subprocess.Popen.__init__(self, [app]+list(args),
1081 stdin=subprocess.PIPE,
1082 stdout=subprocess.PIPE,
1083 stderr=subprocess.PIPE, env=env,
1084 universal_newlines=
True)
1088 """Super class for simple IMP application test cases"""
1089 def _get_application_file_name(self, filename):
1092 if sys.platform ==
'win32':
1100 """Run an application with the given list of arguments.
1101 @return a subprocess.Popen-like object containing the child stdin,
1104 filename = self._get_application_file_name(app)
1105 if sys.platform ==
'win32':
1107 return _SubprocessWrapper(os.path.join(os.environ[
'IMP_BIN_DIR'],
1110 return _SubprocessWrapper(filename, args)
1113 """Run a Python application with the given list of arguments.
1114 The Python application should be self-runnable (i.e. it should
1115 be executable and with a #! on the first line).
1116 @return a subprocess.Popen-like object containing the child stdin,
1120 if sys.executable !=
'/usr/bin/python' and 'IMP_BIN_DIR' in os.environ:
1121 return _SubprocessWrapper(sys.executable,
1122 [os.path.join(os.environ[
'IMP_BIN_DIR'], app)] + args)
1124 return _SubprocessWrapper(app, args)
1127 """Import an installed Python application, rather than running it.
1128 This is useful to directly test components of the application.
1129 @return the Python module object."""
1131 import importlib.machinery
1135 name = os.path.splitext(app)[0]
1136 pathname = os.path.join(os.environ[
'IMP_BIN_DIR'], app)
1138 return importlib.machinery.SourceFileLoader(name,
1139 pathname).load_module()
1141 return imp.load_source(name, pathname)
1144 """Run an application with the given list of arguments.
1145 @return a subprocess.Popen-like object containing the child stdin,
1148 return _SubprocessWrapper(sys.executable, [app]+args)
1151 """Assert that the application exited cleanly (return value = 0)."""
1153 raise OSError(
"Application exited with signal %d\n" % -ret\
1156 self.assertEqual(ret, 0,
1157 "Application exited uncleanly, with exit code %d\n" % ret\
1161 """Read and return a set of shell commands from a doxygen file.
1162 Each command is assumed to be in a \code{.sh}...\endcode block.
1163 The doxygen file is specified relative to the test file itself.
1164 This is used to make sure the commands shown in an application
1165 example actually work (the testcase can also check the resulting
1166 files for correctness)."""
1167 def win32_normpath(p):
1170 return " ".join([os.path.normpath(x)
for x
in p.split()])
1171 def fix_win32_command(cmd):
1173 if cmd.startswith(
'cp -r '):
1174 return 'xcopy /E ' + win32_normpath(cmd[6:])
1175 elif cmd.startswith(
'cp '):
1176 return 'copy ' + win32_normpath(cmd[3:])
1179 d = os.path.dirname(sys.argv[0])
1180 doc = os.path.join(d, doxfile)
1184 with open(doc)
as fh:
1185 for line
in fh.readlines():
1186 if '\code{.sh}' in line:
1188 elif '\endcode' in line:
1191 cmds.append(line.rstrip(
'\r\n').replace(
1192 '<imp_example_path>', example_path))
1193 if sys.platform ==
'win32':
1194 cmds = [fix_win32_command(x)
for x
in cmds]
1198 "Print and run a shell command, as returned by read_shell_commands()"
1201 p = subprocess.call(cmd, shell=
True)
1203 raise OSError(
"%s failed with exit value %d" % (cmd, p))
1207 """Check to make sure the number of C++ object references is as expected"""
1209 def __init__(self, testcase):
1213 IMP._director_objects.cleanup()
1214 self.__testcase = testcase
1216 self.__basenum = IMP.Object.get_number_of_live_objects()
1220 "Make sure that the number of references matches the expected value."
1222 IMP._director_objects.cleanup()
1225 newnum=IMP.Object.get_number_of_live_objects()-self.__basenum
1226 t.assertEqual(newnum, expected,
1227 "Number of objects don't match: "\
1229 +
" != "+ str(expected) +
" found "+\
1235 """Check to make sure the number of director references is as expected"""
1237 def __init__(self, testcase):
1238 IMP._director_objects.cleanup()
1239 self.__testcase = testcase
1240 self.__basenum = IMP._director_objects.get_object_count()
1243 """Make sure that the number of references matches the expected value.
1244 If force_cleanup is set, clean up any unused references first before
1245 doing the assertion.
1249 IMP._director_objects.cleanup()
1250 t.assertEqual(IMP._director_objects.get_object_count() \
1251 - self.__basenum, expected)
1259 if sys.platform ==
'win32' and 'PYTHONPATH' in os.environ \
1260 and 'IMP_BIN_DIR' in os.environ:
1261 libdir = os.environ[
'PYTHONPATH'].split(
';')[0]
1262 bindir = os.environ[
'IMP_BIN_DIR']
1263 path = os.environ[
'PATH']
1264 if libdir
not in path
or bindir
not in path:
1265 os.environ[
'PATH'] = bindir +
';' + libdir +
';' + path
1268 def get_module_version():
1269 """get_module_version() -> std::string const"""
1270 return _IMP_test.get_module_version()
1273 """get_example_path(std::string fname) -> std::string"""
1274 return _IMP_test.get_example_path(fname)
1277 """get_data_path(std::string fname) -> std::string"""
1278 return _IMP_test.get_data_path(fname)
1280 from .
import _version_check
1281 _version_check.check_version(get_module_version())
1282 __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).
def check_get_from
Check that the get_from() static method works correctly.
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.
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 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.
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_test
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.