11 from sys
import version_info
12 if version_info >= (2,6,0):
13 def swig_import_helper():
14 from os.path
import dirname
18 fp, pathname, description = imp.find_module(
'_IMP_test', [dirname(__file__)])
24 _mod = imp.load_module(
'_IMP_test', fp, pathname, description)
28 _IMP_test = swig_import_helper()
29 del swig_import_helper
34 _swig_property = property
37 def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
38 if (name ==
"thisown"):
return self.this.own(value)
40 if type(value).__name__ ==
'SwigPyObject':
41 self.__dict__[name] = value
43 method = class_type.__swig_setmethods__.get(name,
None)
44 if method:
return method(self,value)
46 self.__dict__[name] = value
48 raise AttributeError(
"You cannot add attributes to %s" % self)
50 def _swig_setattr(self,class_type,name,value):
51 return _swig_setattr_nondynamic(self,class_type,name,value,0)
53 def _swig_getattr(self,class_type,name):
54 if (name ==
"thisown"):
return self.this.own()
55 method = class_type.__swig_getmethods__.get(name,
None)
56 if method:
return method(self)
57 raise AttributeError(name)
60 try: strthis =
"proxy of " + self.this.__repr__()
62 return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
67 except AttributeError:
72 def _swig_setattr_nondynamic_method(set):
73 def set_attr(self,name,value):
74 if (name ==
"thisown"):
return self.this.own(value)
75 if hasattr(self,name)
or (name ==
"this"):
78 raise AttributeError(
"You cannot add attributes to %s" % self)
84 weakref_proxy = weakref.proxy
86 weakref_proxy =
lambda x: x
89 class IMP_TEST_SwigPyIterator(object):
90 """Proxy of C++ swig::IMP_TEST_SwigPyIterator class"""
91 thisown = _swig_property(
lambda x: x.this.own(),
lambda x, v: x.this.own(v), doc=
'The membership flag')
92 def __init__(self, *args, **kwargs):
raise AttributeError(
"No constructor defined - class is abstract")
94 __swig_destroy__ = _IMP_test.delete_IMP_TEST_SwigPyIterator
95 __del__ =
lambda self :
None;
97 """value(IMP_TEST_SwigPyIterator self) -> PyObject *"""
98 return _IMP_test.IMP_TEST_SwigPyIterator_value(self)
102 incr(IMP_TEST_SwigPyIterator self, size_t n=1) -> IMP_TEST_SwigPyIterator
103 incr(IMP_TEST_SwigPyIterator self) -> IMP_TEST_SwigPyIterator
105 return _IMP_test.IMP_TEST_SwigPyIterator_incr(self, n)
109 decr(IMP_TEST_SwigPyIterator self, size_t n=1) -> IMP_TEST_SwigPyIterator
110 decr(IMP_TEST_SwigPyIterator self) -> IMP_TEST_SwigPyIterator
112 return _IMP_test.IMP_TEST_SwigPyIterator_decr(self, n)
114 def distance(self, *args):
115 """distance(IMP_TEST_SwigPyIterator self, IMP_TEST_SwigPyIterator x) -> ptrdiff_t"""
116 return _IMP_test.IMP_TEST_SwigPyIterator_distance(self, *args)
118 def equal(self, *args):
119 """equal(IMP_TEST_SwigPyIterator self, IMP_TEST_SwigPyIterator x) -> bool"""
120 return _IMP_test.IMP_TEST_SwigPyIterator_equal(self, *args)
123 """copy(IMP_TEST_SwigPyIterator self) -> IMP_TEST_SwigPyIterator"""
124 return _IMP_test.IMP_TEST_SwigPyIterator_copy(self)
127 """next(IMP_TEST_SwigPyIterator self) -> PyObject *"""
128 return _IMP_test.IMP_TEST_SwigPyIterator_next(self)
131 """__next__(IMP_TEST_SwigPyIterator self) -> PyObject *"""
132 return _IMP_test.IMP_TEST_SwigPyIterator___next__(self)
135 """previous(IMP_TEST_SwigPyIterator self) -> PyObject *"""
136 return _IMP_test.IMP_TEST_SwigPyIterator_previous(self)
138 def advance(self, *args):
139 """advance(IMP_TEST_SwigPyIterator self, ptrdiff_t n) -> IMP_TEST_SwigPyIterator"""
140 return _IMP_test.IMP_TEST_SwigPyIterator_advance(self, *args)
142 def __eq__(self, *args):
143 """__eq__(IMP_TEST_SwigPyIterator self, IMP_TEST_SwigPyIterator x) -> bool"""
144 return _IMP_test.IMP_TEST_SwigPyIterator___eq__(self, *args)
146 def __ne__(self, *args):
147 """__ne__(IMP_TEST_SwigPyIterator self, IMP_TEST_SwigPyIterator x) -> bool"""
148 return _IMP_test.IMP_TEST_SwigPyIterator___ne__(self, *args)
150 def __iadd__(self, *args):
151 """__iadd__(IMP_TEST_SwigPyIterator self, ptrdiff_t n) -> IMP_TEST_SwigPyIterator"""
152 return _IMP_test.IMP_TEST_SwigPyIterator___iadd__(self, *args)
154 def __isub__(self, *args):
155 """__isub__(IMP_TEST_SwigPyIterator self, ptrdiff_t n) -> IMP_TEST_SwigPyIterator"""
156 return _IMP_test.IMP_TEST_SwigPyIterator___isub__(self, *args)
158 def __add__(self, *args):
159 """__add__(IMP_TEST_SwigPyIterator self, ptrdiff_t n) -> IMP_TEST_SwigPyIterator"""
160 return _IMP_test.IMP_TEST_SwigPyIterator___add__(self, *args)
162 def __sub__(self, *args):
164 __sub__(IMP_TEST_SwigPyIterator self, ptrdiff_t n) -> IMP_TEST_SwigPyIterator
165 __sub__(IMP_TEST_SwigPyIterator self, IMP_TEST_SwigPyIterator x) -> ptrdiff_t
167 return _IMP_test.IMP_TEST_SwigPyIterator___sub__(self, *args)
169 def __iter__(self):
return self
170 IMP_TEST_SwigPyIterator_swigregister = _IMP_test.IMP_TEST_SwigPyIterator_swigregister
171 IMP_TEST_SwigPyIterator_swigregister(IMP_TEST_SwigPyIterator)
178 IMP_DEBUG = _IMP_test.IMP_DEBUG
179 IMP_RELEASE = _IMP_test.IMP_RELEASE
180 IMP_SILENT = _IMP_test.IMP_SILENT
181 IMP_PROGRESS = _IMP_test.IMP_PROGRESS
182 IMP_TERSE = _IMP_test.IMP_TERSE
183 IMP_VERBOSE = _IMP_test.IMP_VERBOSE
184 IMP_MEMORY = _IMP_test.IMP_MEMORY
185 IMP_NONE = _IMP_test.IMP_NONE
186 IMP_USAGE = _IMP_test.IMP_USAGE
187 IMP_INTERNAL = _IMP_test.IMP_INTERNAL
188 IMP_BASE_HAS_LOG4CXX = _IMP_test.IMP_BASE_HAS_LOG4CXX
189 IMP_COMPILER_HAS_AUTO = _IMP_test.IMP_COMPILER_HAS_AUTO
190 IMP_COMPILER_HAS_DEBUG_VECTOR = _IMP_test.IMP_COMPILER_HAS_DEBUG_VECTOR
191 IMP_BASE_HAS_BOOST_RANDOM = _IMP_test.IMP_BASE_HAS_BOOST_RANDOM
192 IMP_BASE_HAS_GPERFTOOLS = _IMP_test.IMP_BASE_HAS_GPERFTOOLS
193 IMP_BASE_HAS_TCMALLOC_HEAPCHECKER = _IMP_test.IMP_BASE_HAS_TCMALLOC_HEAPCHECKER
194 IMP_BASE_HAS_TCMALLOC_HEAPPROFILER = _IMP_test.IMP_BASE_HAS_TCMALLOC_HEAPPROFILER
195 IMPBASE_SHOW_WARNINGS = _IMP_test.IMPBASE_SHOW_WARNINGS
197 class _DirectorObjects(object):
198 """@internal Simple class to keep references to director objects
199 to prevent premature deletion."""
202 def register(self, obj):
203 """Take a reference to a director object; will only work for
204 refcounted C++ classes"""
205 if hasattr(obj,
'get_ref_count'):
206 self._objects.append(obj)
208 """Only drop our reference and allow cleanup by Python if no other
209 Python references exist (we hold 3 references: one in self._objects,
210 one in x, and one in the argument list for getrefcount) *and* no
211 other C++ references exist (the Python object always holds one)"""
212 objs = [x
for x
in self._objects
if sys.getrefcount(x) > 3 \
213 or x.get_ref_count() > 1]
217 def get_object_count(self):
218 """Get number of director objects (useful for testing only)"""
219 return len(self._objects)
220 _director_objects = _DirectorObjects()
222 class _ostream(object):
223 """Proxy of C++ std::ostream class"""
224 thisown = _swig_property(
lambda x: x.this.own(),
lambda x, v: x.this.own(v), doc=
'The membership flag')
225 def __init__(self, *args, **kwargs):
raise AttributeError(
"No constructor defined")
226 __repr__ = _swig_repr
227 def write(self, *args):
228 """write(_ostream self, char const * osa_buf)"""
229 return _IMP_test._ostream_write(self, *args)
231 _ostream_swigregister = _IMP_test._ostream_swigregister
232 _ostream_swigregister(_ostream)
234 IMP_COMPILER_HAS_OVERRIDE = _IMP_test.IMP_COMPILER_HAS_OVERRIDE
235 IMP_COMPILER_HAS_FINAL = _IMP_test.IMP_COMPILER_HAS_FINAL
236 IMP_HAS_NOEXCEPT = _IMP_test.IMP_HAS_NOEXCEPT
238 IMP_TEST_HAS_BOOST_FILESYSTEM = _IMP_test.IMP_TEST_HAS_BOOST_FILESYSTEM
239 IMP_TEST_HAS_BOOST_PROGRAMOPTIONS = _IMP_test.IMP_TEST_HAS_BOOST_PROGRAMOPTIONS
240 IMP_TEST_HAS_BOOST_RANDOM = _IMP_test.IMP_TEST_HAS_BOOST_RANDOM
241 IMP_TEST_HAS_BOOST_SYSTEM = _IMP_test.IMP_TEST_HAS_BOOST_SYSTEM
242 IMPTEST_SHOW_WARNINGS = _IMP_test.IMPTEST_SHOW_WARNINGS
243 """@namespace IMP::test
244 @brief Methods and classes for testing the IMP kernel and modules.
258 from .
import _compat_python
259 from ._compat_python
import unittest2
275 def __load_unittest_package():
277 for modname, fromlist
in ((
'unittest', []),
281 u = __import__(modname, {}, {}, fromlist)
282 if hasattr(u,
'skip'):
285 errors.append(
"'%s' does not have the 'skip' decorator" \
287 except ImportError
as e:
288 errors.append(str(e))
290 return _compat_python.unittest2
291 raise ImportError(
"IMP.test requires a newer version of Python's unittest "
292 "package than is available. Either upgrade to a new "
293 "enough Python (at least 2.7 or 3.2) or install the "
294 "unittest2 package. Encountered errors: %s" \
296 unittest = __load_unittest_package()
299 expectedFailure = unittest.expectedFailure
301 skipIf = unittest.skipIf
302 skipUnless = unittest.skipUnless
305 """Simple RAII-style class to run in a temporary directory.
306 When the object is created, the temporary directory is created
307 and becomes the current working directory. When the object goes out
308 of scope, the working directory is reset and the temporary directory
311 self.origdir = os.getcwd()
312 self.tmpdir = tempfile.mkdtemp()
313 os.chdir(self.tmpdir)
315 os.chdir(self.origdir)
316 shutil.rmtree(self.tmpdir, ignore_errors=
True)
320 """Simple RAII-style class to make a temporary directory. When the object
321 is created, the temporary directory is created. When the object goes
322 out of scope, the temporary directory is deleted."""
323 def __init__(self, dir):
324 self.tmpdir = tempfile.mkdtemp(dir=dir)
326 shutil.rmtree(self.tmpdir, ignore_errors=
True)
330 """Calculate the derivative of the single-value function `func` at
331 point `val`. The derivative is calculated using simple finite
332 differences starting with the given `step`; Richardson extrapolation
333 is then used to extrapolate the derivative at step=0."""
338 f1 = func(val + step)
339 f2 = func(val - step)
341 d = [[(f1 - f2) / (2.0 * step)]]
343 for i
in range(1, maxsteps):
344 d.append([0.] * (i + 1))
346 f1 = func(val + step)
347 f2 = func(val - step)
348 d[i][0] = (f1 - f2) / (2.0 * step)
350 for j
in range(1, i + 1):
351 d[i][j] = (d[i][j-1] * fac - d[i-1][j-1]) / (fac - 1.)
353 errt = max(abs(d[i][j] - d[i][j-1]),
354 abs(d[i][j] - d[i-1][j-1]))
358 if abs(d[i][i] - d[i-1][i-1]) >= safe * err:
361 raise ValueError(
"Cannot calculate numerical derivative")
366 """Calculate the x,y and z derivatives of `model`'s scoring function
367 on the `xyz` particle. The derivatives are approximated numerically
368 using the numerical_derivatives() function."""
369 class _XYZDerivativeFunc(object):
370 def __init__(self, xyz, basis_vector):
372 self._model = xyz.get_particle().get_model()
373 self._basis_vector = basis_vector
374 self._starting_coordinates = xyz.get_coordinates()
376 def __call__(self, val):
377 self._xyz.set_coordinates(self._starting_coordinates + \
378 self._basis_vector * val)
379 return self._model.evaluate(
False)
383 for x
in ((1,0,0), (0,1,0), (0,0,1))])
387 """Super class for IMP test cases"""
389 def __init__(self, *args, **keys):
390 unittest.TestCase.__init__(self, *args, **keys)
391 self._progname = os.path.abspath(sys.argv[0])
399 IMP.base.random_number_generator.seed(hash(time.time())%2**30)
406 """Get the full name of an input file in the top-level
408 testdir = os.path.dirname(self._progname)
409 dirs = testdir.split(os.path.sep)
410 for i
in range(len(dirs), 0, -1):
411 input = os.path.sep.join(dirs[:i] + [
'input'])
412 if os.path.isdir(input):
413 ret = os.path.join(input, filename)
414 if not os.path.exists(ret):
415 raise IOError(
"Test input file "+ret+
" does not exist")
417 raise IOError(
"No test input directory found")
420 """Open and return an input file in the top-level test directory."""
424 """Get the full name of an output file in the tmp directory."""
425 if not hasattr(self,
'_tmpdir'):
426 self._tmpdir =
TempDir(os.environ[
'IMP_TMP_DIR'])
427 tmpdir = self._tmpdir.tmpdir
428 return os.path.join(tmpdir, filename)
430 def get_magnitude(self, vector):
431 return sum([x*x
for x
in vector], 0)**.5
435 """Assert that x,y,z analytical derivatives match numerical within
436 a tolerance, or a percentage (of the analytical value), whichever
439 derivs = xyz.get_derivatives()
441 pct = percentage / 100.0
442 self.assertAlmostEqual(self.get_magnitude(derivs-num_derivs),0,
443 delta=tolerance+percentage*self.get_magnitude(num_derivs),
444 msg=
"Don't match "+str(derivs) + str(num_derivs))
445 self.assertAlmostEqual(derivs[0], num_derivs[0],
446 delta=max(tolerance, abs(derivs[0]) * pct))
447 self.assertAlmostEqual(derivs[1], num_derivs[1],
448 delta=max(tolerance, abs(derivs[1]) * pct))
449 self.assertAlmostEqual(derivs[2], num_derivs[2],
450 delta=max(tolerance, abs(derivs[2]) * pct))
453 """Make a particle with optimizable x, y and z attributes, and
454 add it to the model."""
462 """Help handle a test which is expected to fail some fraction of
463 the time. The test is run multiple times and an exception
464 is thrown only if it fails too many times."""
465 prob=chance_of_failure
469 prob= prob*chance_of_failure
470 for i
in range(0, tries):
478 raise AssertError(
"Too many failures")
481 """Estimate how likely a given block of code is to raise an
485 while failures < 10
and tries <1000:
491 return failures/tries
494 """Randomize the xyz coordinates of a list of particles"""
500 p.set_value(xkey, random.uniform(-deviation, deviation))
501 p.set_value(ykey, random.uniform(-deviation, deviation))
502 p.set_value(zkey, random.uniform(-deviation, deviation))
505 """Return distance between two given particles"""
509 dx = p1.get_value(xkey) - p2.get_value(xkey)
510 dy = p1.get_value(ykey) - p2.get_value(ykey)
511 dz = p1.get_value(zkey) - p2.get_value(zkey)
512 return math.sqrt(dx*dx + dy*dy + dz*dz)
515 """Check the unary function func's derivatives against numerical
516 approximations between lb and ub"""
517 for f
in [lb + i * step
for i
in range(1, int((ub-lb)/step))]:
518 (v,d)= func.evaluate_with_derivative(f)
520 self.assertAlmostEqual(d, da, delta=max(abs(.1 *d), 0.01))
523 """Make sure that the minimum of the unary function func over the
524 range between lb and ub is at expected_fmin"""
525 fmin, vmin = lb, func.evaluate(lb)
526 for f
in [lb + i * step
for i
in range(1, int((ub-lb)/step))]:
530 self.assertAlmostEqual(fmin, expected_fmin, delta=step)
533 """Check that the get_from() static method works correctly"""
535 self.assertIsNotNone(cls.get_from(obj))
536 self.assertRaises(ValueError, cls.get_from,
IMP.Model())
541 """Create a bunch of particles in a box"""
546 for i
in range(0,num):
551 def _get_type(self, module, name):
552 return eval(
'type('+module+
"."+name+
')')
554 "Check that all the C++ classes in the module are values or objects."
556 ok = set(exceptions_list + module._value_types + module._object_types + module._raii_types + module._plural_types)
560 if self._get_type(module.__name__, name)==type
and not name.startswith(
"_"):
561 if name.find(
"SwigPyIterator") != -1:
564 if not eval(
'hasattr(%s.%s, "__swig_destroy__")' \
565 % (module.__name__, name)):
570 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." \
572 self.assertEqual(len(bad), 0, message)
573 for e
in exceptions_list:
574 self.assertTrue(e
not in module._value_types
575 + module._object_types
577 + module._plural_types,
578 "Value/Object exception "+e+
" is not an exception")
580 def _check_spelling(self, word, words):
581 """Check that the word is spelled correctly"""
582 if "words" not in dir(self):
584 wordlist= fh.read().split("\n")
586 custom_words=[
"info",
"prechange",
"int",
"ints",
"optimizeds",
"graphviz",
587 "voxel",
"voxels",
"endian",
'rna',
'dna',
588 "xyzr",
"pdbs",
"fft",
"ccc",
"gaussian"]
591 exclude_words = set([
"adapter",
"grey"])
592 self.words=set(wordlist+custom_words) - exclude_words
594 for i
in "0123456789":
599 if word
in self.words:
606 """Check that all the classes in the module follow the imp naming conventions."""
610 cc=re.compile(
"([A-Z][a-z]*)")
612 if self._get_type(module.__name__, name)==type
and not name.startswith(
"_"):
613 if name.find(
"SwigPyIterator") != -1:
615 for t
in re.findall(cc, name):
616 if not self._check_spelling(t.lower(), words):
617 misspelled.append(t.lower())
620 self.assertEqual(len(bad), 0,
621 "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." \
622 % (str(bad),
", ".join(set(misspelled))))
625 if self._get_type(module.__name__, name)==type
and not name.startswith(
"_"):
626 if name.find(
"SwigPyIterator") != -1:
628 if name.find(
'_') != -1:
630 if name.lower== name:
632 for t
in re.findall(cc, name):
633 if not self._check_spelling(t.lower(), words):
634 print(
"misspelled %s in %s" % (t, name))
636 message=
"All IMP classes should have CamelCase names. The following do not: %s." \
638 self.assertEqual(len(bad), 0, message)
640 def _check_function_name(self, prefix, name, verbs, all, exceptions, words,
643 fullname=prefix+
"."+name
646 old_exceptions=[
'unprotected_evaluate',
"unprotected_evaluate_if_good",
647 "unprotected_evaluate_if_below",
648 "after_evaluate",
"before_evaluate",
"has_attribute",
649 "decorate_particle",
"particle_is_instance"]
650 if name
in old_exceptions:
653 if fullname
in exceptions:
655 if name.endswith(
"swigregister"):
657 if name.lower() != name:
658 if name[0].lower() != name[0]
and name.split(
'_')[0]
in all:
663 tokens= name.split(
"_")
664 if tokens[0]
not in verbs:
667 if not self._check_spelling(t, words):
669 print(
"misspelled %s in %s" % (t, name))
673 def _static_method(self, module, prefix, name):
674 """For static methods of the form Foo.bar SWIG creates free functions
675 named Foo_bar. Exclude these from spelling checks since the method
676 Foo.bar has already been checked."""
677 if prefix
is None and '_' in name:
678 modobj = eval(module)
679 cls, meth = name.split(
'_', 1)
680 if hasattr(modobj, cls):
681 clsobj = eval(module +
'.' + cls)
682 if hasattr(clsobj, meth):
685 def _check_function_names(self, module, prefix, names, verbs, all,
686 exceptions, words, misspelled):
689 typ = self._get_type(module, name)
690 if name.startswith(
"_")
or name ==
"weakref_proxy":
692 if typ
in (types.BuiltinMethodType, types.MethodType) \
693 or (typ == types.FunctionType
and \
694 not self._static_method(module, prefix, name)):
695 bad.extend(self._check_function_name(prefix, name, verbs, all,
698 if typ == type
and "SwigPyIterator" not in name:
699 members=eval(
"dir("+module+
"."+name+
")")
700 bad.extend(self._check_function_names(module+
"."+name,
701 name, members, verbs, [],
707 """Check that all the functions in the module follow the IMP
708 naming conventions."""
710 verbs=set([
"add",
"remove",
"get",
"set",
"evaluate",
"compute",
"show",
"create",
"destroy",
711 "push",
"pop",
"write",
"read",
"do",
"show",
"load",
"save",
"reset",
713 "clear",
"handle",
"update",
"apply",
"optimize",
"reserve",
"dump",
714 "propose",
"setup",
"teardown",
"visit",
"find",
"run",
"swap",
"link",
717 bad=self._check_function_names(module.__name__,
None, all, verbs, all, exceptions, words, misspelled)
718 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" \
719 % {
"bad":
"\n".join(bad),
"verbs":verbs}
720 if len(misspelled) > 0:
721 message +=
"\nMisspelled words: " +
", ".join(set(misspelled)) \
722 +
". Add words to the spelling_exceptions variable " \
723 +
"of the standards_exceptions file if needed."
724 self.assertEqual(len(bad), 0, message)
728 """Check that all the classes in modulename have a show method"""
736 if not eval(
'hasattr(%s.%s, "__swig_destroy__")' \
737 % (modulename.__name__, f)):
739 if self._get_type(modulename.__name__, f) == type \
740 and not f.startswith(
"_") \
741 and not f.endswith(
"_swigregister")\
742 and f
not in exceptions\
743 and not f.endswith(
"Temp")
and not f.endswith(
"Iterator")\
744 and not f.endswith(
"Exception")
and\
745 f
not in modulename._raii_types
and \
746 f
not in modulename._plural_types:
747 if not hasattr(getattr(modulename, f),
'show'):
749 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." \
750 %
"\n".join(not_found)
751 self.assertEqual(len(not_found), 0, message)
753 self.assertIn(e, all,
"Show exception "+e+
" is not a class in module")
754 self.assertTrue(
not hasattr(getattr(modulename, e),
'show'),
755 "Exception "+e+
" is not really a show exception")
758 """Run the named example script.
759 A dictionary of all the script's global variables is returned.
760 This can be queried in a test case to make sure the example
761 performed correctly."""
762 class _FatalError(Exception):
pass
766 path, name = os.path.split(filename)
767 oldsyspath = sys.path[:]
768 olssysargv= sys.argv[:]
769 sys.path.insert(0, path)
774 exec(open(filename).read(), vars)
777 except SystemExit
as e:
778 if e.code != 0
and e.code
is not None:
779 raise _FatalError(
"Example exit with code %s" % str(e.code))
783 sys.path = oldsyspath
786 return _ExecDictProxy(vars)
789 """Run a Python module as if with "python -m <modname>",
790 with the given list of arguments as sys.argv.
792 If module is an already-imported Python module, run its 'main'
793 function and return the result.
795 If module is a string, run the module in a subprocess and return
796 a subprocess.Popen-like object containing the child stdin,
800 if type(module) == type(os):
803 mod = __import__(module, {}, {}, [
''])
804 modpath = mod.__file__
805 if modpath.endswith(
'.pyc'):
806 modpath = modpath[:-1]
807 if type(module) == type(os):
808 old_sys_argv = sys.argv
810 IMP.kernel.OptionParser._use_boost_parser =
False
812 sys.argv = [modpath] + args
815 IMP.kernel.OptionParser._use_boost_parser =
True
816 sys.argv = old_sys_argv
818 return _SubprocessWrapper(sys.executable, [modpath] + args)
821 """Check a Python module designed to be runnable with 'python -m'
822 to make sure it supports standard command line options."""
825 out, err = r.communicate()
826 self.assertEqual(r.returncode, 0)
827 self.assertNotEqual(err,
"")
828 self.assertEqual(out,
"")
831 class _ExecDictProxy(object):
832 """exec returns a Python dictionary, which contains IMP objects, other
833 Python objects, as well as base Python modules (such as sys and
834 __builtins__). If we just delete this dictionary, it is entirely
835 possible that base Python modules are removed from the dictionary
836 *before* some IMP objects. This will prevent the IMP objects' Python
837 destructors from running properly, so C++ objects will not be
838 cleaned up. This class proxies the base dict class, and on deletion
839 attempts to remove keys from the dictionary in an order that allows
840 IMP destructors to fire."""
841 def __init__(self, d):
845 module_type = type(IMP)
848 if type(d[k]) != module_type:
851 for meth
in [
'__contains__',
'__getitem__',
'__iter__',
'__len__',
852 'get',
'has_key',
'items',
'keys',
'values']:
853 exec(
"def %s(self, *args, **keys): "
854 "return self._d.%s(*args, **keys)" % (meth, meth))
857 class _TestResult(unittest.TextTestResult):
859 def __init__(self, stream=None, descriptions=None, verbosity=None):
860 super(_TestResult, self).__init__(stream, descriptions, verbosity)
863 def stopTestRun(self):
864 if 'IMP_TEST_DETAIL_DIR' in os.environ:
865 fname = os.path.join(os.environ[
'IMP_TEST_DETAIL_DIR'],
866 os.path.basename(sys.argv[0]))
867 with open(fname,
'wb')
as fh:
868 pickle.dump(self.all_tests, fh, -1)
869 super(_TestResult, self).stopTestRun()
871 def startTest(self, test):
872 super(_TestResult, self).startTest(test)
873 test.start_time=datetime.datetime.now()
875 def _test_finished(self, test, state, detail=None):
876 delta = datetime.datetime.now() - test.start_time
878 pv= delta.total_seconds()
879 except AttributeError:
880 pv = (float(delta.microseconds) \
881 + (delta.seconds + delta.days * 24 * 3600) * 10**6) / 10**6
883 self.stream.write(
"in %.3fs ... " % pv)
884 if detail
is not None and not isinstance(detail, str):
885 detail = self._exc_info_to_string(detail, test)
886 test_doc = self.getDescription(test)
887 test_name = test.id()
888 if test_name.startswith(
'__main__.'):
889 test_name = test_name[9:]
890 self.all_tests.append({
'name': test_name,
891 'docstring': test_doc,
892 'time': pv,
'state': state,
'detail': detail})
894 def addSuccess(self, test):
895 self._test_finished(test,
'OK')
896 super(_TestResult, self).addSuccess(test)
898 def addError(self, test, err):
899 self._test_finished(test,
'ERROR', err)
900 super(_TestResult, self).addError(test, err)
902 def addFailure(self, test, err):
903 self._test_finished(test,
'FAIL', err)
904 super(_TestResult, self).addFailure(test, err)
906 def addSkip(self, test, reason):
907 self._test_finished(test,
'SKIP', reason)
908 super(_TestResult, self).addSkip(test, reason)
910 def addExpectedFailure(self, test, err):
911 self._test_finished(test,
'EXPFAIL', err)
912 super(_TestResult, self).addExpectedFailure(test, err)
914 def addUnexpectedSuccess(self, test):
915 self._test_finished(test,
'UNEXPSUC')
916 super(_TestResult, self).addUnexpectedSuccess(test)
918 def getDescription(self, test):
919 doc_first_line = test.shortDescription()
920 if self.descriptions
and doc_first_line:
921 return doc_first_line
926 class _TestRunner(unittest.TextTestRunner):
927 def _makeResult(self):
928 return _TestResult(self.stream, self.descriptions, self.verbosity)
931 def main(*args, **keys):
932 """Run a set of tests; essentially the same as unittest.main(). Obviates
933 the need to separately import the 'unittest' module, and ensures that
934 main() is from the same unittest module that the IMP.test testcases
936 return unittest.main(testRunner=_TestRunner, *args, **keys)
939 class _SubprocessWrapper(subprocess.Popen):
940 def __init__(self, app, args):
943 if sys.platform ==
'win32' and app != sys.executable:
945 libdir = os.environ[
'PYTHONPATH'].split(
';')[0]
946 env = os.environ.copy()
947 env[
'PATH'] +=
';' + libdir
950 subprocess.Popen.__init__(self, [app]+list(args),
951 stdin=subprocess.PIPE,
952 stdout=subprocess.PIPE,
953 stderr=subprocess.PIPE, env=env,
954 universal_newlines=
True)
958 """Super class for simple IMP application test cases"""
959 def _get_application_file_name(self, filename):
962 if sys.platform ==
'win32':
970 """Run an application with the given list of arguments.
971 @return a subprocess.Popen-like object containing the child stdin,
974 filename = self._get_application_file_name(app)
975 if sys.platform ==
'win32':
977 return _SubprocessWrapper(os.path.join(os.environ[
'IMP_BIN_DIR'],
980 return _SubprocessWrapper(filename, args)
983 """Run a Python application with the given list of arguments.
984 The Python application should be self-runnable (i.e. it should
985 be executable and with a #! on the first line).
986 @return a subprocess.Popen-like object containing the child stdin,
990 if sys.executable !=
'/usr/bin/python':
991 return _SubprocessWrapper(sys.executable,
992 [os.path.join(os.environ[
'IMP_BIN_DIR'], app)] + args)
994 return _SubprocessWrapper(app, args)
997 """Import an installed Python application, rather than running it.
998 This is useful to directly test components of the application.
999 @return the Python module object."""
1001 import importlib.machinery
1005 name = os.path.splitext(app)[0]
1006 pathname = os.path.join(os.environ[
'IMP_BIN_DIR'], app)
1008 return importlib.machinery.SourceFileLoader(name,
1009 pathname).load_module()
1011 return imp.load_source(name, pathname)
1014 """Run an application with the given list of arguments.
1015 @return a subprocess.Popen-like object containing the child stdin,
1018 return _SubprocessWrapper(sys.executable, [app]+args)
1021 """Assert that the application exited cleanly (return value = 0)."""
1023 raise OSError(
"Application exited with signal %d\n" % -ret\
1026 self.assertEqual(ret, 0,
1027 "Application exited uncleanly, with exit code %d\n" % ret\
1031 """Read and return a set of shell commands from a doxygen file.
1032 Each command is assumed to be in a \\code{.sh}...\\endcode block.
1033 The doxygen file is specified relative to the test file itself.
1034 This is used to make sure the commands shown in an application
1035 example actually work (the testcase can also check the resulting
1036 files for correctness)."""
1037 def win32_normpath(p):
1040 return " ".join([os.path.normpath(x)
for x
in p.split()])
1041 def fix_win32_command(cmd):
1043 if cmd.startswith(
'cp -r '):
1044 return 'xcopy /E ' + win32_normpath(cmd[6:])
1045 elif cmd.startswith(
'cp '):
1046 return 'copy ' + win32_normpath(cmd[3:])
1049 d = os.path.dirname(sys.argv[0])
1050 doc = os.path.join(d, doxfile)
1053 example_path = os.path.abspath(IMP.get_example_path(
'..'))
1054 with open(doc)
as fh:
1055 for line
in fh.readlines():
1056 if '\code{.sh}' in line:
1058 elif '\endcode' in line:
1061 cmds.append(line.rstrip(
'\r\n').replace(
1062 '<imp_example_path>', example_path))
1063 if sys.platform ==
'win32':
1064 cmds = [fix_win32_command(x)
for x
in cmds]
1068 "Print and run a shell command, as returned by read_shell_commands()"
1071 p = subprocess.call(cmd, shell=
True)
1073 raise OSError(
"%s failed with exit value %d" % (cmd, p))
1077 """Check to make sure the number of C++ object references is as expected"""
1079 def __init__(self, testcase):
1083 IMP.base._director_objects.cleanup()
1084 self.__testcase = testcase
1086 self.__basenum = IMP.base.Object.get_number_of_live_objects()
1090 "Make sure that the number of references matches the expected value."
1092 IMP.base._director_objects.cleanup()
1095 newnum=IMP.base.Object.get_number_of_live_objects()-self.__basenum
1096 t.assertEqual(newnum, expected,
1097 "Number of objects don't match: "\
1099 +
" != "+ str(expected) +
" found "+\
1105 """Check to make sure the number of director references is as expected"""
1107 def __init__(self, testcase):
1108 IMP.base._director_objects.cleanup()
1109 self.__testcase = testcase
1110 self.__basenum = IMP.base._director_objects.get_object_count()
1113 """Make sure that the number of references matches the expected value.
1114 If force_cleanup is set, clean up any unused references first before
1115 doing the assertion.
1119 IMP.base._director_objects.cleanup()
1120 t.assertEqual(IMP.base._director_objects.get_object_count() \
1121 - self.__basenum, expected)
1129 if sys.platform ==
'win32' and 'PYTHONPATH' in os.environ \
1130 and 'IMP_BIN_DIR' in os.environ:
1131 libdir = os.environ[
'PYTHONPATH'].split(
';')[0]
1132 bindir = os.environ[
'IMP_BIN_DIR']
1133 path = os.environ[
'PATH']
1134 if libdir
not in path
or bindir
not in path:
1135 os.environ[
'PATH'] = bindir +
';' + libdir +
';' + path
1138 def get_module_version():
1139 """get_module_version() -> std::string const"""
1140 return _IMP_test.get_module_version()
1143 """get_example_path(std::string fname) -> std::string"""
1144 return _IMP_test.get_example_path(*args)
1147 """get_data_path(std::string fname) -> std::string"""
1148 return _IMP_test.get_data_path(*args)
1149 from .
import _version_check
1150 _version_check.check_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 assertApplicationExitedCleanly
Assert that the application exited cleanly (return value = 0).
def check_get_from
Check that the get_from() static method works correctly.
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.
Super class for simple IMP application test cases.
void set_check_level(CheckLevel tf)
Control runtime checks in the code.
Low level functionality (logging, error handling, profiling, command line flags etc) that is used by ...
std::string get_example_path(std::string file_name)
Return the path to installed example data for this module.
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()
Vector3D get_random_vector_in(const Cylinder3D &c)
Generate a random vector in a cylinder with uniform density.
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.
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.
Base functionality and abstract base classes for representation, scoring and sampling.
def run_example
Run the named example script.
Class to handle individual model particles.
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.
General purpose algebraic and geometric methods that are expected to be used by a wide variety of IMP...
def numerical_derivative
Calculate the derivative of the single-value function func at point val.
def xyz_numerical_derivatives
Calculate the x,y and z derivatives of model's scoring function 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.
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 installed data.
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.
CheckLevel get_check_level()
Get the current audit mode.
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 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...
Class for storing model, its restraints, constraints, and particles.
Strings get_live_object_names()
Return the names of all live objects.