testing.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. # Copyright 2007 Matt Chaput. All rights reserved.
  2. #
  3. # Redistribution and use in source and binary forms, with or without
  4. # modification, are permitted provided that the following conditions are met:
  5. #
  6. # 1. Redistributions of source code must retain the above copyright notice,
  7. # this list of conditions and the following disclaimer.
  8. #
  9. # 2. Redistributions in binary form must reproduce the above copyright
  10. # notice, this list of conditions and the following disclaimer in the
  11. # documentation and/or other materials provided with the distribution.
  12. #
  13. # THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR
  14. # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  15. # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
  16. # EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  17. # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  18. # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  19. # OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  20. # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  21. # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  22. # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. #
  24. # The views and conclusions contained in the software and documentation are
  25. # those of the authors and should not be interpreted as representing official
  26. # policies, either expressed or implied, of Matt Chaput.
  27. import os.path
  28. import random
  29. import shutil
  30. import sys
  31. import tempfile
  32. from contextlib import contextmanager
  33. from whoosh.filedb.filestore import FileStorage
  34. from whoosh.util import now, random_name
  35. class TempDir(object):
  36. def __init__(self, basename="", parentdir=None, ext=".whoosh",
  37. suppress=frozenset(), keepdir=False):
  38. self.basename = basename or random_name(8)
  39. self.parentdir = parentdir
  40. dirname = parentdir or tempfile.mkdtemp(ext, self.basename)
  41. self.dir = os.path.abspath(dirname)
  42. self.suppress = suppress
  43. self.keepdir = keepdir
  44. def __enter__(self):
  45. if not os.path.exists(self.dir):
  46. os.makedirs(self.dir)
  47. return self.dir
  48. def cleanup(self):
  49. pass
  50. def __exit__(self, exc_type, exc_val, exc_tb):
  51. self.cleanup()
  52. if not self.keepdir:
  53. try:
  54. shutil.rmtree(self.dir)
  55. except OSError:
  56. e = sys.exc_info()[1]
  57. #sys.stderr.write("Can't remove temp dir: " + str(e) + "\n")
  58. #if exc_type is None:
  59. # raise
  60. if exc_type is not None:
  61. if self.keepdir:
  62. sys.stderr.write("Temp dir=" + self.dir + "\n")
  63. if exc_type not in self.suppress:
  64. return False
  65. class TempStorage(TempDir):
  66. def __init__(self, debug=False, **kwargs):
  67. TempDir.__init__(self, **kwargs)
  68. self._debug = debug
  69. def cleanup(self):
  70. self.store.close()
  71. def __enter__(self):
  72. dirpath = TempDir.__enter__(self)
  73. self.store = FileStorage(dirpath, debug=self._debug)
  74. return self.store
  75. class TempIndex(TempStorage):
  76. def __init__(self, schema, ixname='', storage_debug=False, **kwargs):
  77. TempStorage.__init__(self, basename=ixname, debug=storage_debug,
  78. **kwargs)
  79. self.schema = schema
  80. def __enter__(self):
  81. fstore = TempStorage.__enter__(self)
  82. return fstore.create_index(self.schema, indexname=self.basename)
  83. def is_abstract_method(attr):
  84. """Returns True if the given object has __isabstractmethod__ == True.
  85. """
  86. return (hasattr(attr, "__isabstractmethod__")
  87. and getattr(attr, "__isabstractmethod__"))
  88. def check_abstract_methods(base, subclass):
  89. """Raises AssertionError if ``subclass`` does not override a method on
  90. ``base`` that is marked as an abstract method.
  91. """
  92. for attrname in dir(base):
  93. if attrname.startswith("_"):
  94. continue
  95. attr = getattr(base, attrname)
  96. if is_abstract_method(attr):
  97. oattr = getattr(subclass, attrname)
  98. if is_abstract_method(oattr):
  99. raise Exception("%s.%s not overridden"
  100. % (subclass.__name__, attrname))
  101. @contextmanager
  102. def timing(name=None):
  103. t = now()
  104. yield
  105. t = now() - t
  106. print("%s: %0.06f s" % (name or '', t))