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:
74 weakref_proxy = weakref.proxy
76 weakref_proxy =
lambda x: x
79 class IMP_TEST_SwigPyIterator(_object):
80 """Proxy of C++ swig::IMP_TEST_SwigPyIterator class"""
81 __swig_setmethods__ = {}
82 __setattr__ =
lambda self, name, value: _swig_setattr(self, IMP_TEST_SwigPyIterator, name, value)
83 __swig_getmethods__ = {}
84 __getattr__ =
lambda self, name: _swig_getattr(self, IMP_TEST_SwigPyIterator, name)
85 def __init__(self, *args, **kwargs):
raise AttributeError(
"No constructor defined - class is abstract")
87 __swig_destroy__ = _IMP_test.delete_IMP_TEST_SwigPyIterator
88 __del__ =
lambda self :
None;
90 """value(IMP_TEST_SwigPyIterator self) -> PyObject *"""
91 return _IMP_test.IMP_TEST_SwigPyIterator_value(self)
95 incr(IMP_TEST_SwigPyIterator self, size_t n=1) -> IMP_TEST_SwigPyIterator
96 incr(IMP_TEST_SwigPyIterator self) -> IMP_TEST_SwigPyIterator
98 return _IMP_test.IMP_TEST_SwigPyIterator_incr(self, n)
102 decr(IMP_TEST_SwigPyIterator self, size_t n=1) -> IMP_TEST_SwigPyIterator
103 decr(IMP_TEST_SwigPyIterator self) -> IMP_TEST_SwigPyIterator
105 return _IMP_test.IMP_TEST_SwigPyIterator_decr(self, n)
107 def distance(self, *args):
108 """distance(IMP_TEST_SwigPyIterator self, IMP_TEST_SwigPyIterator x) -> ptrdiff_t"""
109 return _IMP_test.IMP_TEST_SwigPyIterator_distance(self, *args)
111 def equal(self, *args):
112 """equal(IMP_TEST_SwigPyIterator self, IMP_TEST_SwigPyIterator x) -> bool"""
113 return _IMP_test.IMP_TEST_SwigPyIterator_equal(self, *args)
116 """copy(IMP_TEST_SwigPyIterator self) -> IMP_TEST_SwigPyIterator"""
117 return _IMP_test.IMP_TEST_SwigPyIterator_copy(self)
120 """next(IMP_TEST_SwigPyIterator self) -> PyObject *"""
121 return _IMP_test.IMP_TEST_SwigPyIterator_next(self)
124 """__next__(IMP_TEST_SwigPyIterator self) -> PyObject *"""
125 return _IMP_test.IMP_TEST_SwigPyIterator___next__(self)
128 """previous(IMP_TEST_SwigPyIterator self) -> PyObject *"""
129 return _IMP_test.IMP_TEST_SwigPyIterator_previous(self)
131 def advance(self, *args):
132 """advance(IMP_TEST_SwigPyIterator self, ptrdiff_t n) -> IMP_TEST_SwigPyIterator"""
133 return _IMP_test.IMP_TEST_SwigPyIterator_advance(self, *args)
135 def __eq__(self, *args):
136 """__eq__(IMP_TEST_SwigPyIterator self, IMP_TEST_SwigPyIterator x) -> bool"""
137 return _IMP_test.IMP_TEST_SwigPyIterator___eq__(self, *args)
139 def __ne__(self, *args):
140 """__ne__(IMP_TEST_SwigPyIterator self, IMP_TEST_SwigPyIterator x) -> bool"""
141 return _IMP_test.IMP_TEST_SwigPyIterator___ne__(self, *args)
143 def __iadd__(self, *args):
144 """__iadd__(IMP_TEST_SwigPyIterator self, ptrdiff_t n) -> IMP_TEST_SwigPyIterator"""
145 return _IMP_test.IMP_TEST_SwigPyIterator___iadd__(self, *args)
147 def __isub__(self, *args):
148 """__isub__(IMP_TEST_SwigPyIterator self, ptrdiff_t n) -> IMP_TEST_SwigPyIterator"""
149 return _IMP_test.IMP_TEST_SwigPyIterator___isub__(self, *args)
151 def __add__(self, *args):
152 """__add__(IMP_TEST_SwigPyIterator self, ptrdiff_t n) -> IMP_TEST_SwigPyIterator"""
153 return _IMP_test.IMP_TEST_SwigPyIterator___add__(self, *args)
155 def __sub__(self, *args):
157 __sub__(IMP_TEST_SwigPyIterator self, ptrdiff_t n) -> IMP_TEST_SwigPyIterator
158 __sub__(IMP_TEST_SwigPyIterator self, IMP_TEST_SwigPyIterator x) -> ptrdiff_t
160 return _IMP_test.IMP_TEST_SwigPyIterator___sub__(self, *args)
162 def __iter__(self):
return self
163 IMP_TEST_SwigPyIterator_swigregister = _IMP_test.IMP_TEST_SwigPyIterator_swigregister
164 IMP_TEST_SwigPyIterator_swigregister(IMP_TEST_SwigPyIterator)
171 IMP_DEBUG = _IMP_test.IMP_DEBUG
172 IMP_RELEASE = _IMP_test.IMP_RELEASE
173 IMP_SILENT = _IMP_test.IMP_SILENT
174 IMP_PROGRESS = _IMP_test.IMP_PROGRESS
175 IMP_TERSE = _IMP_test.IMP_TERSE
176 IMP_VERBOSE = _IMP_test.IMP_VERBOSE
177 IMP_MEMORY = _IMP_test.IMP_MEMORY
178 IMP_NONE = _IMP_test.IMP_NONE
179 IMP_USAGE = _IMP_test.IMP_USAGE
180 IMP_INTERNAL = _IMP_test.IMP_INTERNAL
181 IMP_BASE_HAS_LOG4CXX = _IMP_test.IMP_BASE_HAS_LOG4CXX
182 IMP_COMPILER_HAS_AUTO = _IMP_test.IMP_COMPILER_HAS_AUTO
183 IMP_COMPILER_HAS_DEBUG_VECTOR = _IMP_test.IMP_COMPILER_HAS_DEBUG_VECTOR
184 IMP_BASE_HAS_BOOST_RANDOM = _IMP_test.IMP_BASE_HAS_BOOST_RANDOM
185 IMP_BASE_HAS_GPERFTOOLS = _IMP_test.IMP_BASE_HAS_GPERFTOOLS
186 IMP_BASE_HAS_TCMALLOC_HEAPCHECKER = _IMP_test.IMP_BASE_HAS_TCMALLOC_HEAPCHECKER
187 IMP_BASE_HAS_TCMALLOC_HEAPPROFILER = _IMP_test.IMP_BASE_HAS_TCMALLOC_HEAPPROFILER
188 IMPBASE_SHOW_WARNINGS = _IMP_test.IMPBASE_SHOW_WARNINGS
190 class _DirectorObjects(object):
191 """@internal Simple class to keep references to director objects
192 to prevent premature deletion."""
195 def register(self, obj):
196 """Take a reference to a director object; will only work for
197 refcounted C++ classes"""
198 if hasattr(obj,
'get_ref_count'):
199 self._objects.append(obj)
201 """Only drop our reference and allow cleanup by Python if no other
202 Python references exist (we hold 3 references: one in self._objects,
203 one in x, and one in the argument list for getrefcount) *and* no
204 other C++ references exist (the Python object always holds one)"""
205 objs = [x
for x
in self._objects
if sys.getrefcount(x) > 3 \
206 or x.get_ref_count() > 1]
210 def get_object_count(self):
211 """Get number of director objects (useful for testing only)"""
212 return len(self._objects)
213 _director_objects = _DirectorObjects()
215 DEFAULT_CHECK = _IMP_test.DEFAULT_CHECK
216 NONE = _IMP_test.NONE
217 USAGE = _IMP_test.USAGE
218 USAGE_AND_INTERNAL = _IMP_test.USAGE_AND_INTERNAL
221 """set_check_level(IMP::base::CheckLevel tf)"""
222 return _IMP_test.set_check_level(*args)
225 """get_check_level() -> IMP::base::CheckLevel"""
226 return _IMP_test.get_check_level()
227 class _ostream(_object):
228 """Proxy of C++ std::ostream class"""
229 __swig_setmethods__ = {}
230 __setattr__ =
lambda self, name, value: _swig_setattr(self, _ostream, name, value)
231 __swig_getmethods__ = {}
232 __getattr__ =
lambda self, name: _swig_getattr(self, _ostream, name)
233 def __init__(self, *args, **kwargs):
raise AttributeError(
"No constructor defined")
234 __repr__ = _swig_repr
235 def write(self, *args):
236 """write(_ostream self, char const * osa_buf)"""
237 return _IMP_test._ostream_write(self, *args)
239 _ostream_swigregister = _IMP_test._ostream_swigregister
240 _ostream_swigregister(_ostream)
242 IMP_COMPILER_HAS_OVERRIDE = _IMP_test.IMP_COMPILER_HAS_OVERRIDE
243 IMP_COMPILER_HAS_FINAL = _IMP_test.IMP_COMPILER_HAS_FINAL
244 IMP_HAS_NOEXCEPT = _IMP_test.IMP_HAS_NOEXCEPT
246 IMP_TEST_HAS_BOOST_FILESYSTEM = _IMP_test.IMP_TEST_HAS_BOOST_FILESYSTEM
247 IMP_TEST_HAS_BOOST_PROGRAMOPTIONS = _IMP_test.IMP_TEST_HAS_BOOST_PROGRAMOPTIONS
248 IMP_TEST_HAS_BOOST_RANDOM = _IMP_test.IMP_TEST_HAS_BOOST_RANDOM
249 IMP_TEST_HAS_BOOST_SYSTEM = _IMP_test.IMP_TEST_HAS_BOOST_SYSTEM
250 IMPTEST_SHOW_WARNINGS = _IMP_test.IMPTEST_SHOW_WARNINGS
251 """@namespace IMP::test
252 @brief Methods and classes for testing the IMP kernel and modules.
266 import _compat_python
267 import _compat_python.unittest2
283 def __load_unittest_package():
285 for modname, fromlist
in ((
'unittest', []),
289 u = __import__(modname, {}, {}, fromlist)
290 if hasattr(u,
'skip'):
293 errors.append(
"'%s' does not have the 'skip' decorator" \
295 except ImportError, e:
296 errors.append(str(e))
298 return _compat_python.unittest2
299 raise ImportError(
"IMP.test requires a newer version of Python's unittest "
300 "package than is available. Either upgrade to a new "
301 "enough Python (at least 2.7 or 3.2) or install the "
302 "unittest2 package. Encountered errors: %s" \
304 unittest = __load_unittest_package()
307 expectedFailure = unittest.expectedFailure
309 skipIf = unittest.skipIf
310 skipUnless = unittest.skipUnless
313 """Simple RAII-style class to run in a temporary directory.
314 When the object is created, the temporary directory is created
315 and becomes the current working directory. When the object goes out
316 of scope, the working directory is reset and the temporary directory
319 self.origdir = os.getcwd()
320 self.tmpdir = tempfile.mkdtemp()
321 os.chdir(self.tmpdir)
323 os.chdir(self.origdir)
324 shutil.rmtree(self.tmpdir, ignore_errors=
True)
328 """Simple RAII-style class to make a temporary directory. When the object
329 is created, the temporary directory is created. When the object goes
330 out of scope, the temporary directory is deleted."""
331 def __init__(self, dir):
332 self.tmpdir = tempfile.mkdtemp(dir=dir)
334 shutil.rmtree(self.tmpdir, ignore_errors=
True)
338 """Calculate the derivative of the single-value function `func` at
339 point `val`. The derivative is calculated using simple finite
340 differences starting with the given `step`; Richardson extrapolation
341 is then used to extrapolate the derivative at step=0."""
346 f1 = func(val + step)
347 f2 = func(val - step)
349 d = [[(f1 - f2) / (2.0 * step)]]
351 for i
in range(1, maxsteps):
352 d.append([0.] * (i + 1))
354 f1 = func(val + step)
355 f2 = func(val - step)
356 d[i][0] = (f1 - f2) / (2.0 * step)
358 for j
in range(1, i + 1):
359 d[i][j] = (d[i][j-1] * fac - d[i-1][j-1]) / (fac - 1.)
361 errt = max(abs(d[i][j] - d[i][j-1]),
362 abs(d[i][j] - d[i-1][j-1]))
366 if abs(d[i][i] - d[i-1][i-1]) >= safe * err:
369 raise ValueError(
"Cannot calculate numerical derivative")
374 """Calculate the x,y and z derivatives of `model`'s scoring function
375 on the `xyz` particle. The derivatives are approximated numerically
376 using the numerical_derivatives() function."""
377 class _XYZDerivativeFunc(object):
378 def __init__(self, xyz, basis_vector):
380 self._model = xyz.get_particle().get_model()
381 self._basis_vector = basis_vector
382 self._starting_coordinates = xyz.get_coordinates()
384 def __call__(self, val):
385 self._xyz.set_coordinates(self._starting_coordinates + \
386 self._basis_vector * val)
387 return self._model.evaluate(
False)
391 for x
in ((1,0,0), (0,1,0), (0,0,1))])
395 """Super class for IMP test cases"""
403 IMP.base.random_number_generator.seed(hash(time.time())%2**30)
410 """Get the full name of an input file in the top-level
412 testdir = os.path.dirname(os.path.abspath(sys.argv[0]))
413 dirs = testdir.split(os.path.sep)
414 for i
in range(len(dirs), 0, -1):
415 input = os.path.sep.join(dirs[:i] + [
'input'])
416 if os.path.isdir(input):
417 ret = os.path.join(input, filename)
418 if not open(ret,
"r"):
419 raise IOError(
"Test input file "+ret+
" does not exist")
421 raise IOError(
"No test input directory found")
424 """Open and return an input file in the top-level test directory."""
428 """Get the full name of an output file in the tmp directory."""
429 if not hasattr(self,
'_tmpdir'):
430 self._tmpdir =
TempDir(os.environ[
'IMP_TMP_DIR'])
431 tmpdir = self._tmpdir.tmpdir
432 return os.path.join(tmpdir, filename)
434 def get_magnitude(self, vector):
435 return sum([x*x
for x
in vector], 0)**.5
439 """Assert that x,y,z analytical derivatives match numerical within
440 a tolerance, or a percentage (of the analytical value), whichever
443 derivs = xyz.get_derivatives()
445 pct = percentage / 100.0
446 self.assertAlmostEqual(self.get_magnitude(derivs-num_derivs),0,
447 delta=tolerance+percentage*self.get_magnitude(num_derivs),
448 msg=
"Don't match "+str(derivs) + str(num_derivs))
449 self.assertAlmostEqual(derivs[0], num_derivs[0],
450 delta=max(tolerance, abs(derivs[0]) * pct))
451 self.assertAlmostEqual(derivs[1], num_derivs[1],
452 delta=max(tolerance, abs(derivs[1]) * pct))
453 self.assertAlmostEqual(derivs[2], num_derivs[2],
454 delta=max(tolerance, abs(derivs[2]) * pct))
457 """Make a particle with optimizable x, y and z attributes, and
458 add it to the model."""
466 """Help handle a test which is expected to fail some fraction of
467 the time. The test is run multiple times and an exception
468 is thrown only if it fails too many times."""
469 prob=chance_of_failure
473 prob= prob*chance_of_failure
474 for i
in range(0, tries):
482 raise AssertError(
"Too many failures")
485 """Estimate how likely a given block of code is to raise an
489 while failures < 10
and tries <1000:
495 return failures/tries
498 """Randomize the xyz coordinates of a list of particles"""
504 p.set_value(xkey, random.uniform(-deviation, deviation))
505 p.set_value(ykey, random.uniform(-deviation, deviation))
506 p.set_value(zkey, random.uniform(-deviation, deviation))
509 """Return distance between two given particles"""
513 dx = p1.get_value(xkey) - p2.get_value(xkey)
514 dy = p1.get_value(ykey) - p2.get_value(ykey)
515 dz = p1.get_value(zkey) - p2.get_value(zkey)
516 return math.sqrt(dx*dx + dy*dy + dz*dz)
519 """Check the unary function func's derivatives against numerical
520 approximations between lb and ub"""
521 for f
in [lb + i * step
for i
in range(1, int((ub-lb)/step))]:
522 (v,d)= func.evaluate_with_derivative(f)
524 self.assertAlmostEqual(d, da, delta=max(abs(.1 *d), 0.01))
527 """Make sure that the minimum of the unary function func over the
528 range between lb and ub is at expected_fmin"""
529 fmin, vmin = lb, func.evaluate(lb)
530 for f
in [lb + i * step
for i
in range(1, int((ub-lb)/step))]:
534 self.assertAlmostEqual(fmin, expected_fmin, delta=step)
539 """Create a bunch of particles in a box"""
544 for i
in range(0,num):
549 def _get_type(self, module, name):
550 return eval(
'type('+module+
"."+name+
')')
552 "Check that all the C++ classes in the module are values or objects."
554 ok = set(exceptions_list + eval(module.__name__+
"._value_types") + eval(module.__name__+
"._object_types") + eval(module.__name__+
"._raii_types") +eval(module.__name__+
"._plural_types"))
558 if self._get_type(module.__name__, name)==types.TypeType
and not name.startswith(
"_"):
559 if name.find(
"SwigPyIterator") != -1:
562 if not eval(
'hasattr(%s.%s, "__swig_destroy__")' \
563 % (module.__name__, name)):
568 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." \
570 self.assertEquals(len(bad), 0,
572 for e
in exceptions_list:
573 self.assertTrue(e
not in eval(module.__name__+
"._value_types")\
574 + eval(module.__name__+
"._object_types")\
575 + eval(module.__name__+
"._raii_types")\
576 + eval(module.__name__+
"._plural_types"),
577 "Value/Object exception "+e+
" is not an exception")
579 def _check_spelling(self, word, words):
580 """Check that the word is spelled correctly"""
581 if "words" not in dir(self):
584 custom_words=[
"info",
"prechange",
"int",
"ints",
"optimizeds",
"graphviz",
585 "voxel",
"voxels",
"endian",
'rna',
'dna',
586 "xyzr",
"pdbs",
"fft",
"ccc",
"gaussian"]
589 exclude_words = set([
"adapter",
"grey"])
590 self.words=set(wordlist+custom_words) - exclude_words
592 for i
in "0123456789":
597 if word
in self.words:
604 """Check that all the classes in the module follow the imp naming conventions."""
608 cc=re.compile(
"([A-Z][a-z]*)")
610 if self._get_type(module.__name__, name)==types.TypeType
and not name.startswith(
"_"):
611 if name.find(
"SwigPyIterator") != -1:
613 for t
in re.findall(cc, name):
614 if not self._check_spelling(t.lower(), words):
615 misspelled.append(t.lower())
618 self.assertEquals(len(bad), 0,
619 "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." \
620 % (str(bad),
", ".join(set(misspelled))))
623 if self._get_type(module.__name__, name)==types.TypeType
and not name.startswith(
"_"):
624 if name.find(
"SwigPyIterator") != -1:
626 if name.find(
'_') != -1:
628 if name.lower== name:
630 for t
in re.findall(cc, name):
631 if not self._check_spelling(t.lower(), words):
632 print "misspelled", t,
"in", name
634 message=
"All IMP classes should have CamelCase names. The following do not: %s." \
636 self.assertEquals(len(bad), 0,
639 def _check_function_name(self, prefix, name, verbs, all, exceptions, words,
642 fullname=prefix+
"."+name
645 old_exceptions=[
'unprotected_evaluate',
"unprotected_evaluate_if_good",
646 "unprotected_evaluate_if_below",
647 "after_evaluate",
"before_evaluate",
"has_attribute",
648 "decorate_particle",
"particle_is_instance"]
649 if name
in old_exceptions:
652 if fullname
in exceptions:
654 if name.endswith(
"swigregister"):
656 if name.lower() != name:
657 if name[0].lower() != name[0]
and name.split(
'_')[0]
in all:
662 tokens= name.split(
"_")
663 if tokens[0]
not in verbs:
666 if not self._check_spelling(t, words):
668 print "misspelled", t,
"in", name
672 def _static_method(self, module, prefix, name):
673 """For static methods of the form Foo.bar SWIG creates free functions
674 named Foo_bar. Exclude these from spelling checks since the method
675 Foo.bar has already been checked."""
676 if prefix
is None and '_' in name:
677 modobj = eval(module)
678 cls, meth = name.split(
'_', 1)
679 if hasattr(modobj, cls):
680 clsobj = eval(module +
'.' + cls)
681 if hasattr(clsobj, meth):
684 def _check_function_names(self, module, prefix, names, verbs, all,
685 exceptions, words, misspelled):
688 typ = self._get_type(module, name)
689 if name.startswith(
"_")
or name ==
"weakref_proxy":
691 if typ
in (types.BuiltinMethodType, types.MethodType) \
692 or (typ == types.FunctionType
and \
693 not self._static_method(module, prefix, name)):
694 bad.extend(self._check_function_name(prefix, name, verbs, all,
697 if typ == types.TypeType
and "SwigPyIterator" not in name:
698 members=eval(
"dir("+module+
"."+name+
")")
699 bad.extend(self._check_function_names(module+
"."+name,
700 name, members, verbs, [],
706 """Check that all the functions in the module follow the IMP
707 naming conventions."""
709 verbs=set([
"add",
"remove",
"get",
"set",
"evaluate",
"compute",
"show",
"create",
"destroy",
710 "push",
"pop",
"write",
"read",
"do",
"show",
"load",
"save",
"reset",
712 "clear",
"handle",
"update",
"apply",
"optimize",
"reserve",
"dump",
713 "propose",
"setup",
"teardown",
"visit",
"find",
"run",
"swap",
"link",
716 bad=self._check_function_names(module.__name__,
None, all, verbs, all, exceptions, words, misspelled)
717 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" \
718 % {
"bad":
"\n".join(bad),
"verbs":verbs}
719 if len(misspelled) > 0:
720 message +=
"\nMisspelled words: " +
", ".join(set(misspelled)) \
721 +
". Add words to the spelling_exceptions variable " \
722 +
"of the standards_exceptions file if needed."
723 self.assertEquals(len(bad), 0,
728 """Check that all the classes in modulename have a show method"""
733 if not eval(
'hasattr(%s.%s, "__swig_destroy__")' \
734 % (modulename.__name__, f)):
736 if self._get_type(modulename.__name__, f) == types.TypeType\
737 and not f.startswith(
"_") \
738 and not f.endswith(
"_swigregister")\
739 and f
not in exceptions\
740 and not f.endswith(
"Temp")
and not f.endswith(
"Iterator")\
741 and not f.endswith(
"Exception")
and\
742 f
not in eval(modulename.__name__+
"._raii_types")
and \
743 f
not in eval(modulename.__name__+
"._plural_types"):
744 if not hasattr(getattr(modulename, f),
'show'):
746 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." \
747 %
"\n".join(not_found)
748 self.assertEquals(len(not_found), 0,
751 self.assertIn(e, all,
"Show exception "+e+
" is not a class in module")
752 self.assertTrue(
not hasattr(getattr(modulename, e),
'show'),
753 "Exception "+e+
" is not really a show exception")
756 """Run the named example script.
757 A dictionary of all the script's global variables is returned.
758 This can be queried in a test case to make sure the example
759 performed correctly."""
760 class _FatalError(Exception):
pass
764 path, name = os.path.split(filename)
765 oldsyspath = sys.path[:]
766 olssysargv= sys.argv[:]
767 sys.path.insert(0, path)
772 exec open(filename)
in vars
775 except SystemExit, e:
776 if e.code != 0
and e.code
is not None:
777 raise _FatalError(
"Example exit with code %s" % str(e.code))
781 sys.path = oldsyspath
784 return _ExecDictProxy(vars)
787 """Run a Python module as if with "python -m <modname>",
788 with the given list of arguments as sys.argv.
790 If module is an already-imported Python module, run its 'main'
791 function and return the result.
793 If module is a string, run the module in a subprocess and return
794 a subprocess.Popen-like object containing the child stdin,
798 if type(module) == type(os):
801 mod = __import__(module, {}, {}, [
''])
802 modpath = mod.__file__
803 if modpath.endswith(
'.pyc'):
804 modpath = modpath[:-1]
805 if type(module) == type(os):
806 old_sys_argv = sys.argv
808 IMP.kernel.OptionParser._use_boost_parser =
False
810 sys.argv = [modpath] + args
813 IMP.kernel.OptionParser._use_boost_parser =
True
814 sys.argv = old_sys_argv
816 return _SubprocessWrapper(sys.executable, [modpath] + args)
819 """Check a Python module designed to be runnable with 'python -m'
820 to make sure it supports standard command line options."""
823 out, err = r.communicate()
824 self.assertEqual(r.returncode, 0)
825 self.assertNotEqual(err,
"")
826 self.assertEqual(out,
"")
829 class _ExecDictProxy(object):
830 """exec returns a Python dictionary, which contains IMP objects, other
831 Python objects, as well as base Python modules (such as sys and
832 __builtins__). If we just delete this dictionary, it is entirely
833 possible that base Python modules are removed from the dictionary
834 *before* some IMP objects. This will prevent the IMP objects' Python
835 destructors from running properly, so C++ objects will not be
836 cleaned up. This class proxies the base dict class, and on deletion
837 attempts to remove keys from the dictionary in an order that allows
838 IMP destructors to fire."""
839 def __init__(self, d):
843 module_type = type(IMP)
846 if type(d[k]) != module_type:
849 for meth
in [
'__contains__',
'__getitem__',
'__iter__',
'__len__',
850 'get',
'has_key',
'items',
'keys',
'values']:
851 exec(
"def %s(self, *args, **keys): "
852 "return self._d.%s(*args, **keys)" % (meth, meth))
855 class _TestResult(unittest.TextTestResult):
857 def __init__(self, stream=None, descriptions=None, verbosity=None):
858 super(_TestResult, self).__init__(stream, descriptions, verbosity)
861 def stopTestRun(self):
862 if 'IMP_TEST_DETAIL_DIR' in os.environ:
863 fname = os.path.join(os.environ[
'IMP_TEST_DETAIL_DIR'],
864 os.path.basename(sys.argv[0]))
865 pickle.dump(self.all_tests, open(fname,
'wb'), -1)
866 super(_TestResult, self).stopTestRun()
868 def startTest(self, test):
869 super(_TestResult, self).startTest(test)
870 test.start_time=datetime.datetime.now()
872 def _test_finished(self, test, state, detail=None):
873 delta = datetime.datetime.now() - test.start_time
875 pv= delta.total_seconds()
876 except AttributeError:
877 pv = (float(delta.microseconds) \
878 + (delta.seconds + delta.days * 24 * 3600) * 10**6) / 10**6
880 self.stream.write(
"in %.3fs ... " % pv)
881 if detail
is not None and not isinstance(detail, str):
882 detail = self._exc_info_to_string(detail, test)
883 test_doc = self.getDescription(test)
884 test_name = test.id()
885 if test_name.startswith(
'__main__.'):
886 test_name = test_name[9:]
887 self.all_tests.append({
'name': test_name,
888 'docstring': test_doc,
889 'time': pv,
'state': state,
'detail': detail})
891 def addSuccess(self, test):
892 self._test_finished(test,
'OK')
893 super(_TestResult, self).addSuccess(test)
895 def addError(self, test, err):
896 self._test_finished(test,
'ERROR', err)
897 super(_TestResult, self).addError(test, err)
899 def addFailure(self, test, err):
900 self._test_finished(test,
'FAIL', err)
901 super(_TestResult, self).addFailure(test, err)
903 def addSkip(self, test, reason):
904 self._test_finished(test,
'SKIP', reason)
905 super(_TestResult, self).addSkip(test, reason)
907 def addExpectedFailure(self, test, err):
908 self._test_finished(test,
'EXPFAIL', err)
909 super(_TestResult, self).addExpectedFailure(test, err)
911 def addUnexpectedSuccess(self, test):
912 self._test_finished(test,
'UNEXPSUC')
913 super(_TestResult, self).addUnexpectedSuccess(test)
915 def getDescription(self, test):
916 doc_first_line = test.shortDescription()
917 if self.descriptions
and doc_first_line:
918 return doc_first_line
923 class _TestRunner(unittest.TextTestRunner):
924 def _makeResult(self):
925 return _TestResult(self.stream, self.descriptions, self.verbosity)
928 def main(*args, **keys):
929 """Run a set of tests; essentially the same as unittest.main(). Obviates
930 the need to separately import the 'unittest' module, and ensures that
931 main() is from the same unittest module that the IMP.test testcases
933 return unittest.main(testRunner=_TestRunner, *args, **keys)
937 class _SubprocessWrapper(subprocess.Popen):
938 def __init__(self, app, args):
941 if sys.platform ==
'win32' and app != sys.executable:
943 libdir = os.environ[
'PYTHONPATH'].split(
';')[0]
944 env = os.environ.copy()
945 env[
'PATH'] +=
';' + libdir
948 subprocess.Popen.__init__(self, [app]+list(args),
949 stdin=subprocess.PIPE,
950 stdout=subprocess.PIPE,
951 stderr=subprocess.PIPE, env=env)
956 class _SubprocessWrapper(object):
957 def __init__(self, app, args):
958 self.popen = popen2.Popen3(app +
" " +
" ".join(args),
True)
959 self.stdin = self.popen.tochild
960 self.stdout = self.popen.fromchild
961 self.stderr = self.popen.childerr
963 def _readerthread(self, fh, buffer):
964 buffer.append(fh.read())
966 def communicate(self, input=None):
969 stdout_thread = threading.Thread(target=self._readerthread,
970 args=(self.stdout, stdout))
971 stdout_thread.setDaemon(
True)
972 stdout_thread.start()
973 stderr_thread = threading.Thread(target=self._readerthread,
974 args=(self.stderr, stderr))
975 stderr_thread.setDaemon(
True)
976 stderr_thread.start()
979 self.stdin.write(input)
983 self.returncode = self.popen.wait()
984 return stdout[0], stderr[0]
988 """Super class for simple IMP application test cases"""
989 def _get_application_file_name(self, filename):
992 if sys.platform ==
'win32':
1000 """Run an application with the given list of arguments.
1001 @return a subprocess.Popen-like object containing the child stdin,
1004 filename = self._get_application_file_name(app)
1005 if sys.platform ==
'win32':
1007 return _SubprocessWrapper(os.path.join(os.environ[
'IMP_BIN_DIR'],
1010 return _SubprocessWrapper(filename, args)
1013 """Run a Python application with the given list of arguments.
1014 The Python application should be self-runnable (i.e. it should
1015 be executable and with a #! on the first line).
1016 @return a subprocess.Popen-like object containing the child stdin,
1020 if sys.executable !=
'/usr/bin/python':
1021 return _SubprocessWrapper(sys.executable,
1022 [os.path.join(os.environ[
'IMP_BIN_DIR'], app)] + args)
1024 return _SubprocessWrapper(app, args)
1027 """Import an installed Python application, rather than running it.
1028 This is useful to directly test components of the application.
1029 @return the Python module object."""
1031 return imp.load_source(os.path.splitext(app)[0],
1032 os.path.join(os.environ[
'IMP_BIN_DIR'], app))
1035 """Run an application with the given list of arguments.
1036 @return a subprocess.Popen-like object containing the child stdin,
1039 return _SubprocessWrapper(sys.executable, [app]+args)
1042 """Assert that the application exited cleanly (return value = 0)."""
1044 raise OSError(
"Application exited with signal %d\n" % -ret\
1047 self.assertEqual(ret, 0,
1048 "Application exited uncleanly, with exit code %d\n" % ret\
1052 """Read and return a set of shell commands from a doxygen file.
1053 Each command is assumed to be in a \\code{.sh}...\\endcode block.
1054 The doxygen file is specified relative to the test file itself.
1055 This is used to make sure the commands shown in an application
1056 example actually work (the testcase can also check the resulting
1057 files for correctness)."""
1058 def win32_normpath(p):
1061 return " ".join([os.path.normpath(x)
for x
in p.split()])
1062 def fix_win32_command(cmd):
1064 if cmd.startswith(
'cp -r '):
1065 return 'xcopy /E ' + win32_normpath(cmd[6:])
1066 elif cmd.startswith(
'cp '):
1067 return 'copy ' + win32_normpath(cmd[3:])
1070 d = os.path.dirname(sys.argv[0])
1071 doc = os.path.join(d, doxfile)
1074 example_path = os.path.abspath(IMP.get_example_path(
'..'))
1075 for line
in open(doc).readlines():
1076 if '\code{.sh}' in line:
1078 elif '\endcode' in line:
1081 cmds.append(line.rstrip(
'\r\n').replace(
'<imp_example_path>',
1083 if sys.platform ==
'win32':
1084 cmds = [fix_win32_command(x)
for x
in cmds]
1088 "Print and run a shell command, as returned by read_shell_commands()"
1091 p = subprocess.call(cmd, shell=
True)
1093 raise OSError(
"%s failed with exit value %d" % (cmd, p))
1097 """Check to make sure the number of C++ object references is as expected"""
1099 def __init__(self, testcase):
1103 IMP.base._director_objects.cleanup()
1104 self.__testcase = testcase
1106 self.__basenum = IMP.base.Object.get_number_of_live_objects()
1110 "Make sure that the number of references matches the expected value."
1112 IMP.base._director_objects.cleanup()
1115 newnum=IMP.base.Object.get_number_of_live_objects()-self.__basenum
1116 t.assertEqual(newnum, expected,
1117 "Number of objects don't match: "\
1119 +
" != "+ str(expected) +
" found "+\
1125 """Check to make sure the number of director references is as expected"""
1127 def __init__(self, testcase):
1128 IMP.base._director_objects.cleanup()
1129 self.__testcase = testcase
1130 self.__basenum = IMP.base._director_objects.get_object_count()
1133 """Make sure that the number of references matches the expected value.
1134 If force_cleanup is set, clean up any unused references first before
1135 doing the assertion.
1139 IMP.base._director_objects.cleanup()
1140 t.assertEqual(IMP.base._director_objects.get_object_count() \
1141 - self.__basenum, expected)
1149 if sys.platform ==
'win32' and 'PYTHONPATH' in os.environ \
1150 and 'IMP_BIN_DIR' in os.environ:
1151 libdir = os.environ[
'PYTHONPATH'].split(
';')[0]
1152 bindir = os.environ[
'IMP_BIN_DIR']
1153 path = os.environ[
'PATH']
1154 if libdir
not in path
or bindir
not in path:
1155 os.environ[
'PATH'] = bindir +
';' + libdir +
';' + path
1158 def get_module_version():
1159 """get_module_version() -> std::string const"""
1160 return _IMP_test.get_module_version()
1163 """get_example_path(std::string fname) -> std::string"""
1164 return _IMP_test.get_example_path(*args)
1167 """get_data_path(std::string fname) -> std::string"""
1168 return _IMP_test.get_data_path(*args)
1169 import _version_check
1170 _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 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...
Strings get_live_object_names()
Return the names of all live objects.