IMP logo
IMP Reference Guide  2.10.1
The Integrative Modeling Platform
test/__init__.py
1 # This file was automatically generated by SWIG (http://www.swig.org).
2 # Version 3.0.10
3 #
4 # Do not make changes to this file unless you know what you are doing--modify
5 # the SWIG interface file instead.
6 
7 # This wrapper is part of IMP,
8 # Copyright 2007-2018 IMP Inventors. All rights reserved.
9 
10 from __future__ import print_function, division, absolute_import
11 
12 
13 
14 
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():
18  import importlib
19  pkg = __name__.rpartition('.')[0]
20  mname = '.'.join((pkg, '_IMP_test')).lstrip('.')
21  try:
22  return importlib.import_module(mname)
23  except ImportError:
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
30  import imp
31  fp = None
32  try:
33  fp, pathname, description = imp.find_module('_IMP_test', [dirname(__file__)])
34  except ImportError:
35  import _IMP_test
36  return _IMP_test
37  if fp is not None:
38  try:
39  _mod = imp.load_module('_IMP_test', fp, pathname, description)
40  finally:
41  fp.close()
42  return _mod
43  _IMP_test = swig_import_helper()
44  del swig_import_helper
45 else:
46  import _IMP_test
47 del _swig_python_version_info
48 try:
49  _swig_property = property
50 except NameError:
51  pass # Python < 2.2 doesn't have 'property'.
52 
53 try:
54  import builtins as __builtin__
55 except ImportError:
56  import __builtin__
57 
58 def _swig_setattr_nondynamic(self, class_type, name, value, static=1):
59  if (name == "thisown"):
60  return self.this.own(value)
61  if (name == "this"):
62  if type(value).__name__ == 'SwigPyObject':
63  self.__dict__[name] = value
64  return
65  method = class_type.__swig_setmethods__.get(name, None)
66  if method:
67  return method(self, value)
68  if (not static):
69  object.__setattr__(self, name, value)
70  else:
71  raise AttributeError("You cannot add attributes to %s" % self)
72 
73 
74 def _swig_setattr(self, class_type, name, value):
75  return _swig_setattr_nondynamic(self, class_type, name, value, 0)
76 
77 
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)
82  if method:
83  return method(self)
84  raise AttributeError("'%s' object has no attribute '%s'" % (class_type.__name__, name))
85 
86 
87 def _swig_repr(self):
88  try:
89  strthis = "proxy of " + self.this.__repr__()
90  except __builtin__.Exception:
91  strthis = ""
92  return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
93 
94 
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)
101  else:
102  raise AttributeError("You cannot add attributes to %s" % self)
103  return set_attr
104 
105 
106 try:
107  import weakref
108  weakref_proxy = weakref.proxy
109 except __builtin__.Exception:
110  weakref_proxy = lambda x: x
111 
112 
113 class IMP_TEST_SwigPyIterator(object):
114  """Proxy of C++ swig::IMP_TEST_SwigPyIterator class."""
115 
116  thisown = _swig_property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
117 
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
123 
124  def value(self):
125  """value(IMP_TEST_SwigPyIterator self) -> PyObject *"""
126  return _IMP_test.IMP_TEST_SwigPyIterator_value(self)
127 
128 
129  def incr(self, n=1):
130  """
131  incr(IMP_TEST_SwigPyIterator self, size_t n=1) -> IMP_TEST_SwigPyIterator
132  incr(IMP_TEST_SwigPyIterator self) -> IMP_TEST_SwigPyIterator
133  """
134  return _IMP_test.IMP_TEST_SwigPyIterator_incr(self, n)
135 
136 
137  def decr(self, n=1):
138  """
139  decr(IMP_TEST_SwigPyIterator self, size_t n=1) -> IMP_TEST_SwigPyIterator
140  decr(IMP_TEST_SwigPyIterator self) -> IMP_TEST_SwigPyIterator
141  """
142  return _IMP_test.IMP_TEST_SwigPyIterator_decr(self, n)
143 
144 
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)
148 
149 
150  def equal(self, x):
151  """equal(IMP_TEST_SwigPyIterator self, IMP_TEST_SwigPyIterator x) -> bool"""
152  return _IMP_test.IMP_TEST_SwigPyIterator_equal(self, x)
153 
154 
155  def copy(self):
156  """copy(IMP_TEST_SwigPyIterator self) -> IMP_TEST_SwigPyIterator"""
157  return _IMP_test.IMP_TEST_SwigPyIterator_copy(self)
158 
159 
160  def next(self):
161  """next(IMP_TEST_SwigPyIterator self) -> PyObject *"""
162  return _IMP_test.IMP_TEST_SwigPyIterator_next(self)
163 
164 
165  def __next__(self):
166  """__next__(IMP_TEST_SwigPyIterator self) -> PyObject *"""
167  return _IMP_test.IMP_TEST_SwigPyIterator___next__(self)
168 
169 
170  def previous(self):
171  """previous(IMP_TEST_SwigPyIterator self) -> PyObject *"""
172  return _IMP_test.IMP_TEST_SwigPyIterator_previous(self)
173 
174 
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)
178 
179 
180  def __eq__(self, x):
181  """__eq__(IMP_TEST_SwigPyIterator self, IMP_TEST_SwigPyIterator x) -> bool"""
182  return _IMP_test.IMP_TEST_SwigPyIterator___eq__(self, x)
183 
184 
185  def __ne__(self, x):
186  """__ne__(IMP_TEST_SwigPyIterator self, IMP_TEST_SwigPyIterator x) -> bool"""
187  return _IMP_test.IMP_TEST_SwigPyIterator___ne__(self, x)
188 
189 
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)
193 
194 
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)
198 
199 
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)
203 
204 
205  def __sub__(self, *args):
206  """
207  __sub__(IMP_TEST_SwigPyIterator self, ptrdiff_t n) -> IMP_TEST_SwigPyIterator
208  __sub__(IMP_TEST_SwigPyIterator self, IMP_TEST_SwigPyIterator x) -> ptrdiff_t
209  """
210  return _IMP_test.IMP_TEST_SwigPyIterator___sub__(self, *args)
211 
212  def __iter__(self):
213  return self
214 IMP_TEST_SwigPyIterator_swigregister = _IMP_test.IMP_TEST_SwigPyIterator_swigregister
215 IMP_TEST_SwigPyIterator_swigregister(IMP_TEST_SwigPyIterator)
216 
217 
218 _value_types=[]
219 _object_types=[]
220 _raii_types=[]
221 _plural_types=[]
222 
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
242 
243 import sys
244 class _DirectorObjects(object):
245  """@internal Simple class to keep references to director objects
246  to prevent premature deletion."""
247  def __init__(self):
248  self._objects = []
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)
254  def cleanup(self):
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]
261 # Do in two steps so the references are kept until the end of the
262 # function (deleting references may trigger a fresh call to this method)
263  self._objects = objs
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()
268 
269 class _ostream(object):
270  """Proxy of C++ std::ostream class."""
271 
272  thisown = _swig_property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc='The membership flag')
273 
274  def __init__(self, *args, **kwargs):
275  raise AttributeError("No constructor defined")
276  __repr__ = _swig_repr
277 
278  def write(self, osa_buf):
279  """write(_ostream self, char const * osa_buf)"""
280  return _IMP_test._ostream_write(self, osa_buf)
281 
282 _ostream_swigregister = _IMP_test._ostream_swigregister
283 _ostream_swigregister(_ostream)
284 
285 IMP_COMPILER_HAS_OVERRIDE = _IMP_test.IMP_COMPILER_HAS_OVERRIDE
286 IMP_COMPILER_HAS_FINAL = _IMP_test.IMP_COMPILER_HAS_FINAL
287 IMP_HAS_NOEXCEPT = _IMP_test.IMP_HAS_NOEXCEPT
288 IMP_C_OPEN_BINARY = _IMP_test.IMP_C_OPEN_BINARY
289 import IMP
290 IMP_TEST_HAS_BOOST_FILESYSTEM = _IMP_test.IMP_TEST_HAS_BOOST_FILESYSTEM
291 IMP_TEST_HAS_BOOST_PROGRAMOPTIONS = _IMP_test.IMP_TEST_HAS_BOOST_PROGRAMOPTIONS
292 IMP_TEST_HAS_BOOST_RANDOM = _IMP_test.IMP_TEST_HAS_BOOST_RANDOM
293 IMP_TEST_HAS_BOOST_SYSTEM = _IMP_test.IMP_TEST_HAS_BOOST_SYSTEM
294 IMPTEST_SHOW_WARNINGS = _IMP_test.IMPTEST_SHOW_WARNINGS
295 
296 
297 """@namespace IMP::test
298  @brief Methods and classes for testing the IMP kernel and modules.
299  @ingroup python
300 """
301 
302 import re, math
303 import sys
304 import os
305 import re
306 import tempfile
307 import random
308 import IMP
309 import time
310 import types
311 import shutil
312 import difflib
313 import pprint
314 from . import _compat_python
315 from ._compat_python import unittest2
316 from ._compat_python.unittest2.util import safe_repr
317 import datetime
318 import pickle
319 import contextlib
320 
321 # Fall back to the sets.Set class on older Pythons that don't have
322 # the 'set' builtin type.
323 try:
324  set = set
325 except NameError:
326  import sets
327  set = sets.Set
328 
329 # Load a new enough unittest package (should have the 'skip' decorator)
330 # - On Python 2.7 or 3.2, the standard 'unittest' package will work.
331 # - On older Pythons, use the 'unittest2' package if available, otherwise use
332 # our bundled version of this package.
333 def __load_unittest_package():
334  errors = []
335  for modname, fromlist in (('unittest', []),
336  ('unittest2', []),
337  ):
338  try:
339  u = __import__(modname, {}, {}, fromlist)
340  if hasattr(u, 'skip'):
341  return u
342  else:
343  errors.append("'%s' does not have the 'skip' decorator" \
344  % modname)
345  except ImportError as e:
346  errors.append(str(e))
347 #u = __import__("_compat_python.unittest2
348  return _compat_python.unittest2
349  raise ImportError("IMP.test requires a newer version of Python's unittest "
350  "package than is available. Either upgrade to a new "
351  "enough Python (at least 2.7 or 3.2) or install the "
352  "unittest2 package. Encountered errors: %s" \
353  % "; ".join(errors))
354 unittest = __load_unittest_package()
355 
356 # Expose some unittest decorators for convenience
357 expectedFailure = unittest.expectedFailure
358 skip = unittest.skip
359 skipIf = unittest.skipIf
360 skipUnless = unittest.skipUnless
361 
362 @IMP.deprecated_object("2.7", "Use temporary_working_directory() instead.")
363 class RunInTempDir(object):
364  """Simple RAII-style class to run in a temporary directory.
365  When the object is created, the temporary directory is created
366  and becomes the current working directory. When the object goes out
367  of scope, the working directory is reset and the temporary directory
368  deleted."""
369  def __init__(self):
370  self.origdir = os.getcwd()
371  self.tmpdir = tempfile.mkdtemp()
372  os.chdir(self.tmpdir)
373  def __del__(self):
374  os.chdir(self.origdir)
375  shutil.rmtree(self.tmpdir, ignore_errors=True)
376 
377 @contextlib.contextmanager
379  """Simple context manager to run in a temporary directory.
380  While the context manager is active (within the 'with' block)
381  the current working directory is set to a temporary directory.
382  When the context manager exists, the working directory is reset
383  and the temporary directory deleted."""
384  origdir = os.getcwd()
385  tmpdir = tempfile.mkdtemp()
386  os.chdir(tmpdir)
387  yield tmpdir
388  os.chdir(origdir)
389  shutil.rmtree(tmpdir, ignore_errors=True)
390 
391 @IMP.deprecated_object("2.7", "Use temporary_directory() instead.")
392 class TempDir(object):
393  """Simple RAII-style class to make a temporary directory. When the object
394  is created, the temporary directory is created. When the object goes
395  out of scope, the temporary directory is deleted."""
396  def __init__(self, dir=None):
397  self.tmpdir = tempfile.mkdtemp(dir=dir)
398  def __del__(self):
399  shutil.rmtree(self.tmpdir, ignore_errors=True)
400 
401 class _TempDir(object):
402  def __init__(self, dir=None):
403  self.tmpdir = tempfile.mkdtemp(dir=dir)
404  def __del__(self):
405  shutil.rmtree(self.tmpdir, ignore_errors=True)
406 
407 @contextlib.contextmanager
408 def temporary_directory(dir=None):
409  """Simple context manager to make a temporary directory.
410  The temporary directory has the same lifetime as the context manager
411  (i.e. it is created at the start of the 'with' block, and deleted
412  at the end of the block).
413  @param dir If given, the temporary directory is made as a subdirectory
414  of that directory, rather than in the default temporary
415  directory location (e.g. /tmp)
416  @return the full path to the temporary directory.
417  """
418  tmpdir = tempfile.mkdtemp(dir=dir)
419  yield tmpdir
420  shutil.rmtree(tmpdir, ignore_errors=True)
421 
422 def numerical_derivative(func, val, step):
423  """Calculate the derivative of the single-value function `func` at
424  point `val`. The derivative is calculated using simple finite
425  differences starting with the given `step`; Richardson extrapolation
426  is then used to extrapolate the derivative at step=0."""
427  maxsteps = 50
428  con = 1.4
429  safe = 2.0
430  err = 1.0e30
431  f1 = func(val + step)
432  f2 = func(val - step)
433 # create first element in triangular matrix d of derivatives
434  d = [[(f1 - f2) / (2.0 * step)]]
435  retval = None
436  for i in range(1, maxsteps):
437  d.append([0.] * (i + 1))
438  step /= con
439  f1 = func(val + step)
440  f2 = func(val - step)
441  d[i][0] = (f1 - f2) / (2.0 * step)
442  fac = con * con
443  for j in range(1, i + 1):
444  d[i][j] = (d[i][j-1] * fac - d[i-1][j-1]) / (fac - 1.)
445  fac *= con * con
446  errt = max(abs(d[i][j] - d[i][j-1]),
447  abs(d[i][j] - d[i-1][j-1]))
448  if errt <= err:
449  err = errt
450  retval = d[i][j]
451  if abs(d[i][i] - d[i-1][i-1]) >= safe * err:
452  break
453  if retval is None:
454  raise ValueError("Cannot calculate numerical derivative")
455  return retval
456 
457 
458 def xyz_numerical_derivatives(sf, xyz, step):
459  """Calculate the x,y and z derivatives of the scoring function `sf`
460  on the `xyz` particle. The derivatives are approximated numerically
461  using the numerical_derivatives() function."""
462  class _XYZDerivativeFunc(object):
463  def __init__(self, sf, xyz, basis_vector):
464  self._xyz = xyz
465  self._sf = sf
466  self._basis_vector = basis_vector
467  self._starting_coordinates = xyz.get_coordinates()
468 
469  def __call__(self, val):
470  self._xyz.set_coordinates(self._starting_coordinates + \
471  self._basis_vector * val)
472  return self._sf.evaluate(False)
473 
474  return tuple([IMP.test.numerical_derivative(_XYZDerivativeFunc(sf, xyz,
475  IMP.algebra.Vector3D(*x)), 0, 0.01) \
476  for x in ((1,0,0), (0,1,0), (0,0,1))])
477 
478 
479 class TestCase(unittest.TestCase):
480  """Super class for IMP test cases.
481  This provides a number of useful IMP-specific methods on top of
482  the standard Python `unittest.TestCase` class.
483  Test scripts should generally contain a subclass of this class,
484  conventionally called `Tests` (this makes it easier to run an
485  individual test from the commane line) and use IMP::test::main()
486  as their main function."""
487 
488 # Provide assert(Not)Regex for Python 2 users (assertRegexMatches is
489 # deprecated in Python 3)
490  if not hasattr(unittest.TestCase, 'assertRegex'):
491  assertRegex = unittest.TestCase.assertRegexpMatches
492  assertNotRegex = unittest.TestCase.assertNotRegexpMatches
493 
494  def __init__(self, *args, **keys):
495  unittest.TestCase.__init__(self, *args, **keys)
496  self._progname = os.path.abspath(sys.argv[0])
497 
498  def setUp(self):
499  self.__check_level = IMP.get_check_level()
500 # Turn on expensive runtime checks while running the test suite:
501  IMP.set_check_level(IMP.USAGE_AND_INTERNAL)
502 # python ints are bigger than C++ ones, so we need to make sure it fits
503 # otherwise python throws fits
504  IMP.random_number_generator.seed(hash(time.time())%2**30)
505 
506  def tearDown(self):
507 # Restore original check level
508  IMP.set_check_level(self.__check_level)
509 # Clean up any temporary files
510  if hasattr(self, '_tmpdir'):
511  del self._tmpdir
512 
513  def get_input_file_name(self, filename):
514  """Get the full name of an input file in the top-level
515  test directory."""
516  testdir = os.path.dirname(self._progname)
517  if self.__module__ != '__main__':
518  testdir = os.path.dirname(sys.modules[self.__module__].__file__)
519  dirs = testdir.split(os.path.sep)
520  for i in range(len(dirs), 0, -1):
521  input = os.path.sep.join(dirs[:i] + ['input'])
522  if os.path.isdir(input):
523  ret = os.path.join(input, filename)
524  if not os.path.exists(ret):
525  raise IOError("Test input file "+ret+" does not exist")
526  return ret
527  raise IOError("No test input directory found")
528 
529  def open_input_file(self, filename, mode='rb'):
530  """Open and return an input file in the top-level test directory."""
531  return open(self.get_input_file_name(filename), mode)
532 
533  def get_tmp_file_name(self, filename):
534  """Get the full name of an output file in the tmp directory.
535  The directory containing this file will be automatically
536  cleaned up when the test completes."""
537  if not hasattr(self, '_tmpdir'):
538  self._tmpdir = _TempDir(os.environ['IMP_TMP_DIR'])
539  tmpdir = self._tmpdir.tmpdir
540  return os.path.join(tmpdir, filename)
541 
542  def get_magnitude(self, vector):
543  """Get the magnitude of a list of floats"""
544  return sum([x*x for x in vector], 0)**.5
545 
546  def assertRaisesUsageException(self, c, *args, **keys):
547  """Assert that the given callable object raises UsageException.
548  This differs from unittest's assertRaises in that the test
549  is skipped in fast mode (where usage checks are turned off)."""
550  if IMP.get_check_level() >= IMP.USAGE:
551  return self.assertRaises(IMP.UsageException, c, *args, **keys)
552 
553  def assertRaisesInternalException(self, c, *args, **keys):
554  """Assert that the given callable object raises InternalException.
555  This differs from unittest's assertRaises in that the test
556  is skipped in fast mode (where internal checks are turned off)."""
557  if IMP.get_check_level() >= IMP.USAGE_AND_INTERNAL:
558  return self.assertRaises(IMP.InternalException, c, *args, **keys)
559 
560  def assertNotImplemented(self, c, *args, **keys):
561  """Assert that the given callable object is not implemented."""
562  return self.assertRaises(IMP.InternalException, c, *args, **keys)
563 
564  def assertXYZDerivativesInTolerance(self, sf, xyz, tolerance=0,
565  percentage=0):
566  """Assert that x,y,z analytical derivatives match numerical within
567  a tolerance, or a percentage (of the analytical value), whichever
568  is larger. `sf` should be a ScoringFunction or Restraint,
569  although for backwards compatibility a Model is also accepted."""
570  sf.evaluate(True)
571  derivs = xyz.get_derivatives()
572  num_derivs = xyz_numerical_derivatives(sf, xyz, 0.01)
573  pct = percentage / 100.0
574  self.assertAlmostEqual(self.get_magnitude(derivs-num_derivs),0,
575  delta=tolerance+percentage*self.get_magnitude(num_derivs),
576  msg="Don't match "+str(derivs) + str(num_derivs))
577  self.assertAlmostEqual(derivs[0], num_derivs[0],
578  delta=max(tolerance, abs(derivs[0]) * pct))
579  self.assertAlmostEqual(derivs[1], num_derivs[1],
580  delta=max(tolerance, abs(derivs[1]) * pct))
581  self.assertAlmostEqual(derivs[2], num_derivs[2],
582  delta=max(tolerance, abs(derivs[2]) * pct))
583 
584  def assertSequenceAlmostEqual(self, first, second, places=None, msg=None,
585  delta=None):
586  """Fail if the difference between any two items in the two sequences
587  are exceed the specified number of places or delta. See
588  `assertAlmostEqual`.
589  """
590  if delta is not None and places is not None:
591  raise TypeError("specify delta or places not both")
592 
593  ftype = type(first)
594  ftypename = ftype.__name__
595  stype = type(second)
596  stypename = stype.__name__
597  if ftype != stype:
598  raise self.failureException(
599  'Sequences are of different types: %s != %s' % (
600  ftypename, stypename))
601 
602  try:
603  flen = len(first)
604  except (NotImplementedError, TypeError):
605  raise self.failureException(
606  'First %s has no length' % (ftypename))
607  try:
608  slen = len(second)
609  except (NotImplementedError, TypeError):
610  raise self.failureException(
611  'Second %s has no length' % (stypename))
612 
613  if flen != slen:
614  raise self.failureException(
615  'Sequences have non equal lengths: %d != %d' % (flen, slen))
616 
617  differing = None
618  for i in range(min(flen, slen)):
619  differing = '%ss differ: %s != %s\n' % (
620  ftypename.capitalize(), safe_repr(first),
621  safe_repr(second))
622 
623  try:
624  f = first[i]
625  except (TypeError, IndexError, NotImplementedError):
626  differing += ('\nUnable to index element %d of first %s\n' %
627  (i, ftypename))
628  break
629 
630  try:
631  s = second[i]
632  except (TypeError, IndexError, NotImplementedError):
633  differing += ('\nUnable to index element %d of second %s\n' %
634  (i, stypename))
635  break
636 
637  try:
638  self.assertAlmostEqual(
639  f, s, places=places, msg=msg, delta=delta)
640  except (TypeError, ValueError, NotImplementedError, AssertionError):
641  differing += (
642  "\nFirst differing element "
643  "%d:\n%s\n%s\n") % (i, safe_repr(f), safe_repr(s))
644  break
645  else:
646  return
647 
648  standardMsg = differing
649  diffMsg = '\n' + '\n'.join(
650  difflib.ndiff(pprint.pformat(first).splitlines(),
651  pprint.pformat(second).splitlines()))
652  standardMsg = self._truncateMessage(standardMsg, diffMsg)
653  msg = self._formatMessage(msg, standardMsg)
654  raise self.failureException(msg)
655 
656  def create_point_particle(self, model, x, y, z):
657  """Make a particle with optimizable x, y and z attributes, and
658  add it to the model."""
659  p = IMP.Particle(model)
660  p.add_attribute(IMP.FloatKey("x"), x, True)
661  p.add_attribute(IMP.FloatKey("y"), y, True)
662  p.add_attribute(IMP.FloatKey("z"), z, True)
663  return p
664 
665  def probabilistic_check(self, testcall, chance_of_failure):
666  """Help handle a test which is expected to fail some fraction of
667  the time. The test is run multiple times and an exception
668  is thrown only if it fails too many times.
669  @note Use of this function should be avoided. If there is a corner
670  case that results in a test 'occasionally' failing, write a
671  new test specifically for that corner case and assert that
672  it fails consistently (and remove the corner case from the
673  old test).
674  """
675  prob=chance_of_failure
676  tries=1
677  while prob > .001:
678  tries=tries+1
679  prob= prob*chance_of_failure
680  for i in range(0, tries):
681  try:
682  eval(testcall)
683  except:
684  pass
685  else:
686  return
687  eval(testcall)
688  raise AssertError("Too many failures")
689 
690  def failure_probability(self, testcall):
691  """Estimate how likely a given block of code is to raise an
692  AssertionError."""
693  failures=0
694  tries=0.0
695  while failures < 10 and tries <1000:
696  try:
697  eval(testcall)
698  except:
699  failures=failures+1
700  tries=tries+1
701  return failures/tries
702 
703  def randomize_particles(self, particles, deviation):
704  """Randomize the xyz coordinates of a list of particles"""
705 # Note: cannot use XYZ here since that pulls in IMP.core
706  xkey = IMP.FloatKey("x")
707  ykey = IMP.FloatKey("y")
708  zkey = IMP.FloatKey("z")
709  for p in particles:
710  p.set_value(xkey, random.uniform(-deviation, deviation))
711  p.set_value(ykey, random.uniform(-deviation, deviation))
712  p.set_value(zkey, random.uniform(-deviation, deviation))
713 
714  def particle_distance(self, p1, p2):
715  """Return distance between two given particles"""
716  xkey = IMP.FloatKey("x")
717  ykey = IMP.FloatKey("y")
718  zkey = IMP.FloatKey("z")
719  dx = p1.get_value(xkey) - p2.get_value(xkey)
720  dy = p1.get_value(ykey) - p2.get_value(ykey)
721  dz = p1.get_value(zkey) - p2.get_value(zkey)
722  return math.sqrt(dx*dx + dy*dy + dz*dz)
723 
724  def check_unary_function_deriv(self, func, lb, ub, step):
725  """Check the unary function func's derivatives against numerical
726  approximations between lb and ub"""
727  for f in [lb + i * step for i in range(1, int((ub-lb)/step))]:
728  (v,d)= func.evaluate_with_derivative(f)
729  da = numerical_derivative(func.evaluate, f, step / 10.)
730  self.assertAlmostEqual(d, da, delta=max(abs(.1 *d), 0.01))
731 
732  def check_unary_function_min(self, func, lb, ub, step, expected_fmin):
733  """Make sure that the minimum of the unary function func over the
734  range between lb and ub is at expected_fmin"""
735  fmin, vmin = lb, func.evaluate(lb)
736  for f in [lb + i * step for i in range(1, int((ub-lb)/step))]:
737  v = func.evaluate(f)
738  if v < vmin:
739  fmin, vmin = f, v
740  self.assertAlmostEqual(fmin, expected_fmin, delta=step)
741 
743  """Check methods that every IMP::Object class should have"""
744  obj.set_was_used(True)
745 # Test get_from static method
746  cls = type(obj)
747  self.assertIsNotNone(cls.get_from(obj))
748  self.assertRaises(ValueError, cls.get_from, IMP.Model())
749 # Test __str__ and __repr__
750  self.assertIsInstance(str(obj), str)
751  self.assertIsInstance(repr(obj), str)
752 # Test get_version_info()
753  verinf = obj.get_version_info()
754  self.assertIsInstance(verinf, IMP.VersionInfo)
755 # Test SWIG thisown flag
756  o = obj.thisown
757  obj.thisown = o
758 
759  def create_particles_in_box(self, model, num=10,
760  lb= [0,0,0],
761  ub= [10,10,10]):
762  """Create a bunch of particles in a box"""
763  import IMP.algebra
764  lbv=IMP.algebra.Vector3D(lb[0],lb[1],lb[2])
765  ubv=IMP.algebra.Vector3D(ub[0],ub[1],ub[2])
766  ps= []
767  for i in range(0,num):
769  p = self.create_point_particle(model, v[0], v[1], v[2])
770  ps.append(p)
771  return ps
772  def _get_type(self, module, name):
773  return eval('type('+module+"."+name+')')
774  def assertValueObjects(self, module, exceptions_list):
775  "Check that all the C++ classes in the module are values or objects."
776  all= dir(module)
777  ok = set(exceptions_list + module._value_types + module._object_types + module._raii_types + module._plural_types)
778 
779  bad=[]
780  for name in all:
781  if self._get_type(module.__name__, name)==type and not name.startswith("_"):
782  if name.find("SwigPyIterator") != -1:
783  continue
784 # Exclude Python-only classes
785  if not eval('hasattr(%s.%s, "__swig_destroy__")' \
786  % (module.__name__, name)):
787  continue
788  if name in ok:
789  continue
790  bad.append(name)
791  message="All IMP classes should be labeled as values or objects to get memory management correct in Python. The following are not:\n%s\nPlease add an IMP_SWIG_OBJECT or IMP_SWIG_VALUE call to the Python wrapper, or if the class has a good reason to be neither, add the name to the value_object_exceptions list in the IMPModuleTest call." \
792  % (str(bad))
793  self.assertEqual(len(bad), 0, message)
794  for e in exceptions_list:
795  self.assertTrue(e not in module._value_types
796  + module._object_types
797  + module._raii_types
798  + module._plural_types,
799  "Value/Object exception "+e+" is not an exception")
800 
801  def _check_spelling(self, word, words):
802  """Check that the word is spelled correctly"""
803  if "words" not in dir(self):
804  with open(IMP.test.get_data_path("linux.words"), "r") as fh:
805  wordlist= fh.read().split("\n")
806 # why is "all" missing on my mac?
807  custom_words=["info", "prechange", "int", "ints", "optimizeds", "graphviz",
808  "voxel", "voxels", "endian", 'rna', 'dna',
809  "xyzr", "pdbs", "fft", "ccc", "gaussian"]
810 # Exclude some common alternative spellings - we want to
811 # be consistent
812  exclude_words = set(["adapter", "grey"])
813  self.words=set(wordlist+custom_words) - exclude_words
814  if self.words:
815  for i in "0123456789":
816  if i in word:
817  return True
818  if word in words:
819  return True
820  if word in self.words:
821  return True
822  else:
823  return False
824  else:
825  return True
826  def assertClassNames(self, module, exceptions, words):
827  """Check that all the classes in the module follow the IMP
828  naming conventions."""
829  all= dir(module)
830  misspelled = []
831  bad=[]
832  cc=re.compile("([A-Z][a-z]*)")
833  for name in all:
834  if self._get_type(module.__name__, name)==type and not name.startswith("_"):
835  if name.find("SwigPyIterator") != -1:
836  continue
837  for t in re.findall(cc, name):
838  if not self._check_spelling(t.lower(), words):
839  misspelled.append(t.lower())
840  bad.append(name)
841 
842  self.assertEqual(len(bad), 0,
843  "All IMP classes should be properly spelled. The following are not: %s.\nMisspelled words: %s. Add words to the spelling_exceptions variable of the IMPModuleTest if needed." \
844  % (str(bad), ", ".join(set(misspelled))))
845 
846  for name in all:
847  if self._get_type(module.__name__, name)==type and not name.startswith("_"):
848  if name.find("SwigPyIterator") != -1:
849  continue
850  if name.find('_') != -1:
851  bad.append(name)
852  if name.lower== name:
853  bad.append(name)
854  for t in re.findall(cc, name):
855  if not self._check_spelling(t.lower(), words):
856  print("misspelled %s in %s" % (t, name))
857  bad.append(name)
858  message="All IMP classes should have CamelCase names. The following do not: %s." \
859  % ("\n".join(bad))
860  self.assertEqual(len(bad), 0, message)
861 
862  def _check_function_name(self, prefix, name, verbs, all, exceptions, words,
863  misspelled):
864  if prefix:
865  fullname=prefix+"."+name
866  else:
867  fullname=name
868  old_exceptions=['unprotected_evaluate', "unprotected_evaluate_if_good",
869  "unprotected_evaluate_if_below",
870  "after_evaluate", "before_evaluate", "has_attribute",
871  "decorate_particle","particle_is_instance"]
872  if name in old_exceptions:
873  return []
874 #print "name", fullname
875  if fullname in exceptions:
876  return []
877  if name.endswith("swigregister"):
878  return []
879  if name.lower() != name:
880  if name[0].lower() != name[0] and name.split('_')[0] in all:
881 # static methods
882  return []
883  else:
884  return [fullname]
885  tokens= name.split("_")
886  if tokens[0] not in verbs:
887  return [fullname]
888  for t in tokens:
889  if not self._check_spelling(t, words):
890  misspelled.append(t)
891  print("misspelled %s in %s" % (t, name))
892  return [fullname]
893  return []
894 
895  def _static_method(self, module, prefix, name):
896  """For static methods of the form Foo.bar SWIG creates free functions
897  named Foo_bar. Exclude these from spelling checks since the method
898  Foo.bar has already been checked."""
899  if prefix is None and '_' in name:
900  modobj = eval(module)
901  cls, meth = name.split('_', 1)
902  if hasattr(modobj, cls):
903  clsobj = eval(module + '.' + cls)
904  if hasattr(clsobj, meth):
905  return True
906 
907  def _check_function_names(self, module, prefix, names, verbs, all,
908  exceptions, words, misspelled):
909  bad=[]
910  for name in names:
911  typ = self._get_type(module, name)
912  if name.startswith("_") or name =="weakref_proxy":
913  continue
914  if typ in (types.BuiltinMethodType, types.MethodType) \
915  or (typ == types.FunctionType and \
916  not self._static_method(module, prefix, name)):
917  bad.extend(self._check_function_name(prefix, name, verbs, all,
918  exceptions, words,
919  misspelled))
920  if typ == type and "SwigPyIterator" not in name:
921  members=eval("dir("+module+"."+name+")")
922  bad.extend(self._check_function_names(module+"."+name,
923  name, members, verbs, [],
924  exceptions, words,
925  misspelled))
926  return bad
927 
928  def assertFunctionNames(self, module, exceptions, words):
929  """Check that all the functions in the module follow the IMP
930  naming conventions."""
931  all= dir(module)
932  verbs=set(["add", "remove", "get", "set", "evaluate", "compute", "show", "create", "destroy",
933  "push", "pop", "write", "read", "do", "show", "load", "save", "reset",
934  "accept", "reject",
935  "clear", "handle", "update", "apply", "optimize", "reserve", "dump",
936  "propose", "setup", "teardown", "visit", "find", "run", "swap", "link",
937  "validate"])
938  misspelled = []
939  bad=self._check_function_names(module.__name__, None, all, verbs, all, exceptions, words, misspelled)
940  message="All IMP methods and functions should have lower case names separated by underscores and beginning with a verb, preferably one of ['add', 'remove', 'get', 'set', 'create', 'destroy']. Each of the words should be a properly spelled English word. The following do not (given our limited list of verbs that we check for):\n%(bad)s\nIf there is a good reason for them not to (eg it does start with a verb, just one with a meaning that is not covered by the normal list), add them to the function_name_exceptions variable in the standards_exceptions file. Otherwise, please fix. The current verb list is %(verbs)s" \
941  % {"bad":"\n".join(bad), "verbs":verbs}
942  if len(misspelled) > 0:
943  message += "\nMisspelled words: " + ", ".join(set(misspelled)) \
944  + ". Add words to the spelling_exceptions variable " \
945  + "of the standards_exceptions file if needed."
946  self.assertEqual(len(bad), 0, message)
947 
948 
949  def assertShow(self, modulename, exceptions):
950  """Check that all the classes in modulename have a show method"""
951  all= dir(modulename)
952  not_found=[]
953  for f in all:
954 # Exclude SWIG C global variables object
955  if f == 'cvar':
956  continue
957 # Exclude Python-only classes; they are all showable
958  if not eval('hasattr(%s.%s, "__swig_destroy__")' \
959  % (modulename.__name__, f)):
960  continue
961  if self._get_type(modulename.__name__, f) == type \
962  and not f.startswith("_") \
963  and not f.endswith("_swigregister")\
964  and f not in exceptions\
965  and not f.endswith("Temp") and not f.endswith("Iterator")\
966  and not f.endswith("Exception") and\
967  f not in modulename._raii_types and \
968  f not in modulename._plural_types:
969  if not hasattr(getattr(modulename, f), 'show'):
970  not_found.append(f)
971  message="All IMP classes should support show and __str__. The following do not:\n%s\n If there is a good reason for them not to, add them to the show_exceptions variable in the IMPModuleTest call. Otherwise, please fix." \
972  % "\n".join(not_found)
973  self.assertEqual(len(not_found), 0, message)
974  for e in exceptions:
975  self.assertIn(e, all, "Show exception "+e+" is not a class in module")
976  self.assertTrue(not hasattr(getattr(modulename, e), 'show'),
977  "Exception "+e+" is not really a show exception")
978 
979  def run_example(self, filename):
980  """Run the named example script.
981  @return a dictionary of all the script's global variables.
982  This can be queried in a test case to make sure
983  the example performed correctly."""
984  class _FatalError(Exception): pass
985 
986 # Add directory containing the example to sys.path, so it can import
987 # other Python modules in the same directory
988  path, name = os.path.split(filename)
989  oldsyspath = sys.path[:]
990  olssysargv= sys.argv[:]
991  sys.path.insert(0, path)
992  sys.argv=[filename]
993  vars = {}
994  try:
995  try:
996  exec(open(filename).read(), vars)
997 # Catch sys.exit() called from within the example; a non-zero exit
998 # value should cause the test case to fail
999  except SystemExit as e:
1000  if e.code != 0 and e.code is not None:
1001  raise _FatalError("Example exit with code %s" % str(e.code))
1002  finally:
1003 # Restore sys.path (note that Python 2.3 does not allow
1004 # try/except/finally, so we need to use nested trys)
1005  sys.path = oldsyspath
1006  sys.argv= olssysargv
1007 
1008  return _ExecDictProxy(vars)
1009 
1010  def run_python_module(self, module, args):
1011  """Run a Python module as if with "python -m <modname>",
1012  with the given list of arguments as sys.argv.
1013 
1014  If module is an already-imported Python module, run its 'main'
1015  function and return the result.
1016 
1017  If module is a string, run the module in a subprocess and return
1018  a subprocess.Popen-like object containing the child stdin,
1019  stdout and stderr.
1020  """
1021  def mock_setup_from_argv(*args, **kwargs):
1022 # do-nothing replacement for boost command line parser
1023  pass
1024  if type(module) == type(os):
1025  mod = module
1026  else:
1027  mod = __import__(module, {}, {}, [''])
1028  modpath = mod.__file__
1029  if modpath.endswith('.pyc'):
1030  modpath = modpath[:-1]
1031  if type(module) == type(os):
1032  old_sys_argv = sys.argv
1033 # boost parser doesn't like being called multiple times per process
1034  old_setup = IMP.setup_from_argv
1035  IMP.setup_from_argv = mock_setup_from_argv
1036  try:
1037  sys.argv = [modpath] + args
1038  return module.main()
1039  finally:
1040  IMP.setup_from_argv = old_setup
1041  sys.argv = old_sys_argv
1042  else:
1043  return _SubprocessWrapper(sys.executable, [modpath] + args)
1044 
1045  def check_runnable_python_module(self, module):
1046  """Check a Python module designed to be runnable with 'python -m'
1047  to make sure it supports standard command line options."""
1048 # --help should return with exit 0, no errors
1049  r = self.run_python_module(module, ['--help'])
1050  out, err = r.communicate()
1051  self.assertEqual(r.returncode, 0)
1052  self.assertNotEqual(err, "")
1053  self.assertEqual(out, "")
1054 
1055 
1056 class _ExecDictProxy(object):
1057  """exec returns a Python dictionary, which contains IMP objects, other
1058  Python objects, as well as base Python modules (such as sys and
1059  __builtins__). If we just delete this dictionary, it is entirely
1060  possible that base Python modules are removed from the dictionary
1061  *before* some IMP objects. This will prevent the IMP objects' Python
1062  destructors from running properly, so C++ objects will not be
1063  cleaned up. This class proxies the base dict class, and on deletion
1064  attempts to remove keys from the dictionary in an order that allows
1065  IMP destructors to fire."""
1066  def __init__(self, d):
1067  self._d = d
1068  def __del__(self):
1069 # Try to release example objects in a sensible order
1070  module_type = type(IMP)
1071  d = self._d
1072  for k in d.keys():
1073  if type(d[k]) != module_type:
1074  del d[k]
1075 
1076  for meth in ['__contains__', '__getitem__', '__iter__', '__len__',
1077  'get', 'has_key', 'items', 'keys', 'values']:
1078  exec("def %s(self, *args, **keys): "
1079  "return self._d.%s(*args, **keys)" % (meth, meth))
1080 
1081 
1082 class _TestResult(unittest.TextTestResult):
1083 
1084  def __init__(self, stream=None, descriptions=None, verbosity=None):
1085  super(_TestResult, self).__init__(stream, descriptions, verbosity)
1086  self.all_tests = []
1087 
1088  def stopTestRun(self):
1089  if 'IMP_TEST_DETAIL_DIR' in os.environ:
1090  fname = os.path.join(os.environ['IMP_TEST_DETAIL_DIR'],
1091  os.path.basename(sys.argv[0]))
1092  with open(fname, 'wb') as fh:
1093  pickle.dump(self.all_tests, fh, -1)
1094  super(_TestResult, self).stopTestRun()
1095 
1096  def startTest(self, test):
1097  super(_TestResult, self).startTest(test)
1098  test.start_time=datetime.datetime.now()
1099 
1100  def _test_finished(self, test, state, detail=None):
1101  delta = datetime.datetime.now() - test.start_time
1102  try:
1103  pv= delta.total_seconds()
1104  except AttributeError:
1105  pv = (float(delta.microseconds) \
1106  + (delta.seconds + delta.days * 24 * 3600) * 10**6) / 10**6
1107  if pv > 1:
1108  self.stream.write("in %.3fs ... " % pv)
1109  if detail is not None and not isinstance(detail, str):
1110  detail = self._exc_info_to_string(detail, test)
1111  test_doc = self.getDescription(test)
1112  test_name = test.id()
1113  if test_name.startswith('__main__.'):
1114  test_name = test_name[9:]
1115  self.all_tests.append({'name': test_name,
1116  'docstring': test_doc,
1117  'time': pv, 'state': state, 'detail': detail})
1118 
1119  def addSuccess(self, test):
1120  self._test_finished(test, 'OK')
1121  super(_TestResult, self).addSuccess(test)
1122 
1123  def addError(self, test, err):
1124  self._test_finished(test, 'ERROR', err)
1125  super(_TestResult, self).addError(test, err)
1126 
1127  def addFailure(self, test, err):
1128  self._test_finished(test, 'FAIL', err)
1129  super(_TestResult, self).addFailure(test, err)
1130 
1131  def addSkip(self, test, reason):
1132  self._test_finished(test, 'SKIP', reason)
1133  super(_TestResult, self).addSkip(test, reason)
1134 
1135  def addExpectedFailure(self, test, err):
1136  self._test_finished(test, 'EXPFAIL', err)
1137  super(_TestResult, self).addExpectedFailure(test, err)
1138 
1139  def addUnexpectedSuccess(self, test):
1140  self._test_finished(test, 'UNEXPSUC')
1141  super(_TestResult, self).addUnexpectedSuccess(test)
1142 
1143  def getDescription(self, test):
1144  doc_first_line = test.shortDescription()
1145  if self.descriptions and doc_first_line:
1146  return doc_first_line
1147  else:
1148  return str(test)
1149 
1150 
1151 class _TestRunner(unittest.TextTestRunner):
1152  def _makeResult(self):
1153  return _TestResult(self.stream, self.descriptions, self.verbosity)
1154 
1155 
1156 def main(*args, **keys):
1157  """Run a set of tests; similar to unittest.main().
1158  Obviates the need to separately import the 'unittest' module, and
1159  ensures that main() is from the same unittest module that the
1160  IMP.test testcases are. In addition, turns on some extra checks
1161  (e.g. trying to use deprecated code will cause an exception
1162  to be thrown)."""
1163  import IMP
1165  return unittest.main(testRunner=_TestRunner, *args, **keys)
1166 
1167 import subprocess
1168 class _SubprocessWrapper(subprocess.Popen):
1169  def __init__(self, app, args):
1170 # For (non-Python) applications to work on Windows, the
1171 # PATH must include the directory containing built DLLs
1172  if sys.platform == 'win32' and app != sys.executable:
1173 # Hack to find the location of build/lib/
1174  libdir = os.environ['PYTHONPATH'].split(';')[0]
1175  env = os.environ.copy()
1176  env['PATH'] += ';' + libdir
1177  else:
1178  env = None
1179  subprocess.Popen.__init__(self, [app]+list(args),
1180  stdin=subprocess.PIPE,
1181  stdout=subprocess.PIPE,
1182  stderr=subprocess.PIPE, env=env,
1183  universal_newlines=True)
1184 
1185 
1187  """Super class for simple IMP application test cases"""
1188  def _get_application_file_name(self, filename):
1189 # If we ran from run-all-tests.py, it set an env variable for us with
1190 # the top-level test directory
1191  if sys.platform == 'win32':
1192  filename += '.exe'
1193 #if 'IMP_BUILD_ROOT' in os.environ:
1194 # testdir = os.environ['IMP_BUILD_ROOT']
1195 # return os.path.join(testdir, "build", "bin", filename)
1196  return filename
1197 
1198  def run_application(self, app, args):
1199  """Run an application with the given list of arguments.
1200  @return a subprocess.Popen-like object containing the child stdin,
1201  stdout and stderr.
1202  """
1203  filename = self._get_application_file_name(app)
1204  if sys.platform == 'win32':
1205 # Cannot rely on PATH on wine builds, so use full pathname
1206  return _SubprocessWrapper(os.path.join(os.environ['IMP_BIN_DIR'],
1207  filename), args)
1208  else:
1209  return _SubprocessWrapper(filename, args)
1210 
1211  def run_python_application(self, app, args):
1212  """Run a Python application with the given list of arguments.
1213  The Python application should be self-runnable (i.e. it should
1214  be executable and with a #! on the first line).
1215  @return a subprocess.Popen-like object containing the child stdin,
1216  stdout and stderr.
1217  """
1218 # Handle platforms where /usr/bin/python doesn't work
1219  if sys.executable != '/usr/bin/python' and 'IMP_BIN_DIR' in os.environ:
1220  return _SubprocessWrapper(sys.executable,
1221  [os.path.join(os.environ['IMP_BIN_DIR'], app)] + args)
1222  else:
1223  return _SubprocessWrapper(app, args)
1224 
1226  """Import an installed Python application, rather than running it.
1227  This is useful to directly test components of the application.
1228  @return the Python module object."""
1229  try:
1230  import importlib.machinery
1231  imp = None
1232  except ImportError:
1233  import imp
1234  name = os.path.splitext(app)[0]
1235  pathname = os.path.join(os.environ['IMP_BIN_DIR'], app)
1236  if imp is None:
1237  return importlib.machinery.SourceFileLoader(name,
1238  pathname).load_module()
1239  else:
1240  return imp.load_source(name, pathname)
1241 
1242  def run_script(self, app, args):
1243  """Run an application with the given list of arguments.
1244  @return a subprocess.Popen-like object containing the child stdin,
1245  stdout and stderr.
1246  """
1247  return _SubprocessWrapper(sys.executable, [app]+args)
1248 
1249  def assertApplicationExitedCleanly(self, ret, error):
1250  """Assert that the application exited cleanly (return value = 0)."""
1251  if ret < 0:
1252  raise OSError("Application exited with signal %d\n" % -ret\
1253  +error)
1254  else:
1255  self.assertEqual(ret, 0,
1256  "Application exited uncleanly, with exit code %d\n" % ret\
1257  + error)
1258 
1259  def read_shell_commands(self, doxfile):
1260  """Read and return a set of shell commands from a doxygen file.
1261  Each command is assumed to be in a \code{.sh}...\endcode block.
1262  The doxygen file is specified relative to the test file itself.
1263  This is used to make sure the commands shown in an application
1264  example actually work (the testcase can also check the resulting
1265  files for correctness)."""
1266  def win32_normpath(p):
1267 # Sometimes Windows can read Unix-style paths, but sometimes it
1268 # gets confused... so normalize all paths to be sure
1269  return " ".join([os.path.normpath(x) for x in p.split()])
1270  def fix_win32_command(cmd):
1271 # Make substitutions so a Unix shell command works on Windows
1272  if cmd.startswith('cp -r '):
1273  return 'xcopy /E ' + win32_normpath(cmd[6:])
1274  elif cmd.startswith('cp '):
1275  return 'copy ' + win32_normpath(cmd[3:])
1276  else:
1277  return cmd
1278  d = os.path.dirname(sys.argv[0])
1279  doc = os.path.join(d, doxfile)
1280  inline = False
1281  cmds = []
1282  example_path = os.path.abspath(IMP.get_example_path('..'))
1283  with open(doc) as fh:
1284  for line in fh.readlines():
1285  if '\code{.sh}' in line:
1286  inline = True
1287  elif '\endcode' in line:
1288  inline = False
1289  elif inline:
1290  cmds.append(line.rstrip('\r\n').replace(
1291  '<imp_example_path>', example_path))
1292  if sys.platform == 'win32':
1293  cmds = [fix_win32_command(x) for x in cmds]
1294  return cmds
1295 
1296  def run_shell_command(self, cmd):
1297  "Print and run a shell command, as returned by read_shell_commands()"
1298  import subprocess
1299  print(cmd)
1300  p = subprocess.call(cmd, shell=True)
1301  if p != 0:
1302  raise OSError("%s failed with exit value %d" % (cmd, p))
1303 
1304 
1305 class RefCountChecker(object):
1306  """Check to make sure the number of C++ object references is as expected"""
1307 
1308  def __init__(self, testcase):
1309 # Make sure no director objects are hanging around; otherwise these
1310 # may be unexpectedly garbage collected later, decreasing the
1311 # live object count
1312  IMP._director_objects.cleanup()
1313  self.__testcase = testcase
1314  if IMP.get_check_level() >= IMP.USAGE_AND_INTERNAL:
1315  self.__basenum = IMP.Object.get_number_of_live_objects()
1316  self.__names= IMP.get_live_object_names()
1317 
1318  def assert_number(self, expected):
1319  "Make sure that the number of references matches the expected value."
1320  t = self.__testcase
1321  IMP._director_objects.cleanup()
1322  if IMP.get_check_level() >= IMP.USAGE_AND_INTERNAL:
1323  newnames=[x for x in IMP.get_live_object_names() if x not in self.__names]
1324  newnum=IMP.Object.get_number_of_live_objects()-self.__basenum
1325  t.assertEqual(newnum, expected,
1326  "Number of objects don't match: "\
1327  +str(newnum)\
1328  +" != "+ str(expected) +" found "+\
1329  str(newnames))
1330 
1331 
1332 
1334  """Check to make sure the number of director references is as expected"""
1335 
1336  def __init__(self, testcase):
1337  IMP._director_objects.cleanup()
1338  self.__testcase = testcase
1339  self.__basenum = IMP._director_objects.get_object_count()
1340 
1341  def assert_number(self, expected, force_cleanup=True):
1342  """Make sure that the number of references matches the expected value.
1343  If force_cleanup is set, clean up any unused references first before
1344  doing the assertion.
1345  """
1346  t = self.__testcase
1347  if force_cleanup:
1348  IMP._director_objects.cleanup()
1349  t.assertEqual(IMP._director_objects.get_object_count() \
1350  - self.__basenum, expected)
1351 
1352 # Make sure that the IMP binary directory (build/bin) is in the PATH, if
1353 # we're running under wine (the imppy.sh script normally ensures this, but
1354 # wine overrides the PATH). This is needed so that tests of imported Python
1355 # applications can successfully spawn C++ applications (e.g. idock.py tries
1356 # to run recompute_zscore.exe). build/lib also needs to be in the PATH, since
1357 # that's how Windows locates dependent DLLs such as libimp.dll.
1358 if sys.platform == 'win32' and 'PYTHONPATH' in os.environ \
1359  and 'IMP_BIN_DIR' in os.environ:
1360  libdir = os.environ['PYTHONPATH'].split(';')[0]
1361  bindir = os.environ['IMP_BIN_DIR']
1362  path = os.environ['PATH']
1363  if libdir not in path or bindir not in path:
1364  os.environ['PATH'] = bindir + ';' + libdir + ';' + path
1365 
1366 
1367 def get_module_version():
1368  """get_module_version() -> std::string const"""
1369  return _IMP_test.get_module_version()
1370 
1371 def get_example_path(fname):
1372  """get_example_path(std::string fname) -> std::string"""
1373  return _IMP_test.get_example_path(fname)
1374 
1375 def get_data_path(fname):
1376  """get_data_path(std::string fname) -> std::string"""
1377  return _IMP_test.get_data_path(fname)
1378 
1379 from . import _version_check
1380 _version_check.check_version(get_module_version())
1381 __version__ = get_module_version()
1382 
1383 
1384 
def run_python_module
Run a Python module as if with "python -m <modname>", with the given list of arguments as sys...
def temporary_working_directory
Simple context manager to run in a temporary directory.
def assertApplicationExitedCleanly
Assert that the application exited cleanly (return value = 0).
CheckLevel get_check_level()
Get the current audit mode.
Definition: exception.h:81
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.
Definition: exception.h:102
def main
Run a set of tests; similar to unittest.main().
An exception for an invalid usage of IMP.
Definition: exception.h:123
Super class for simple IMP application test cases.
def assertRaisesInternalException
Assert that the given callable object raises InternalException.
std::string get_example_path(std::string file_name)
Return the full path to one of this module's example files.
def assert_number
Make sure that the number of references matches the expected value.
Check to make sure the number of director references is as expected.
def assertShow
Check that all the classes in modulename have a show method.
def run_shell_command
Print and run a shell command, as returned by read_shell_commands()
def assertRaisesUsageException
Assert that the given callable object raises UsageException.
Vector3D get_random_vector_in(const Cylinder3D &c)
Generate a random vector in a cylinder with uniform density.
def assertSequenceAlmostEqual
Fail if the difference between any two items in the two sequences are exceed the specified number of ...
Class for storing model, its restraints, constraints, and particles.
Definition: Model.h:72
def run_python_application
Run a Python application with the given list of arguments.
def assert_number
Make sure that the number of references matches the expected value.
Simple RAII-style class to run in a temporary directory.
Strings get_live_object_names()
Return the names of all live objects.
def check_standard_object_methods
Check methods that every IMP::Object class should have.
def particle_distance
Return distance between two given particles.
def check_unary_function_deriv
Check the unary function func's derivatives against numerical approximations between lb and ub...
def get_tmp_file_name
Get the full name of an output file in the tmp directory.
Version and module information for Objects.
Definition: VersionInfo.h:28
def run_example
Run the named example script.
def get_magnitude
Get the magnitude of a list of floats.
void set_deprecation_exceptions(bool tf)
Toggle whether an exception is thrown when a deprecated method is used.
def check_unary_function_min
Make sure that the minimum of the unary function func over the range between lb and ub is at expected...
def probabilistic_check
Help handle a test which is expected to fail some fraction of the time.
def create_particles_in_box
Create a bunch of particles in a box.
def deprecated_object
Python decorator to mark a class as deprecated.
Definition: __init__.py:9687
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.
Definition: exception.h:49
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.
VectorD< 3 > Vector3D
Definition: VectorD.h:395
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.
Definition: Particle.h:41
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.
Definition: exception.h:73