1 """Support code for distutils test cases.""" 2 import os 3 import shutil 4 import tempfile 5 from copy import deepcopy 6 import warnings 7 8 from distutils import log 9 from distutils.log import DEBUG, INFO, WARN, ERROR, FATAL 10 from distutils.core import Distribution 11 12 def capture_warnings(func): 13 def _capture_warnings(*args, **kw): 14 with warnings.catch_warnings(): 15 warnings.simplefilter("ignore") 16 return func(*args, **kw) 17 return _capture_warnings 18 19 class LoggingSilencer(object): 20 21 def setUp(self): 22 super(LoggingSilencer, self).setUp() 23 self.threshold = log.set_threshold(log.FATAL) 24 # catching warnings 25 # when log will be replaced by logging 26 # we won't need such monkey-patch anymore 27 self._old_log = log.Log._log 28 log.Log._log = self._log 29 self.logs = [] 30 31 def tearDown(self): 32 log.set_threshold(self.threshold) 33 log.Log._log = self._old_log 34 super(LoggingSilencer, self).tearDown() 35 36 def _log(self, level, msg, args): 37 if level not in (DEBUG, INFO, WARN, ERROR, FATAL): 38 raise ValueError('%s wrong log level' % str(level)) 39 self.logs.append((level, msg, args)) 40 41 def get_logs(self, *levels): 42 def _format(msg, args): 43 if len(args) == 0: 44 return msg 45 return msg % args 46 return [_format(msg, args) for level, msg, args 47 in self.logs if level in levels] 48 49 def clear_logs(self): 50 self.logs = [] 51 52 class TempdirManager(object): 53 """Mix-in class that handles temporary directories for test cases. 54 55 This is intended to be used with unittest.TestCase. 56 """ 57 58 def setUp(self): 59 super(TempdirManager, self).setUp() 60 self.tempdirs = [] 61 62 def tearDown(self): 63 super(TempdirManager, self).tearDown() 64 while self.tempdirs: 65 d = self.tempdirs.pop() 66 shutil.rmtree(d, os.name in ('nt', 'cygwin')) 67 68 def mkdtemp(self): 69 """Create a temporary directory that will be cleaned up. 70 71 Returns the path of the directory. 72 """ 73 d = tempfile.mkdtemp() 74 self.tempdirs.append(d) 75 return d 76 77 def write_file(self, path, content='xxx'): 78 """Writes a file in the given path. 79 80 81 path can be a string or a sequence. 82 """ 83 if isinstance(path, (list, tuple)): 84 path = os.path.join(*path) 85 f = open(path, 'w') 86 try: 87 f.write(content) 88 finally: 89 f.close() 90 91 def create_dist(self, pkg_name='foo', **kw): 92 """Will generate a test environment. 93 94 This function creates: 95 - a Distribution instance using keywords 96 - a temporary directory with a package structure 97 98 It returns the package directory and the distribution 99 instance. 100 """ 101 tmp_dir = self.mkdtemp() 102 pkg_dir = os.path.join(tmp_dir, pkg_name) 103 os.mkdir(pkg_dir) 104 dist = Distribution(attrs=kw) 105 106 return pkg_dir, dist 107 108 class DummyCommand: 109 """Class to store options for retrieval via set_undefined_options().""" 110 111 def __init__(self, **kwargs): 112 for kw, val in kwargs.items(): 113 setattr(self, kw, val) 114 115 def ensure_finalized(self): 116 pass 117 118 class EnvironGuard(object): 119 120 def setUp(self): 121 super(EnvironGuard, self).setUp() 122 self.old_environ = deepcopy(os.environ) 123 124 def tearDown(self): 125 for key, value in self.old_environ.items(): 126 if os.environ.get(key) != value: 127 os.environ[key] = value 128 129 for key in os.environ.keys(): 130 if key not in self.old_environ: 131 del os.environ[key] 132 133 super(EnvironGuard, self).tearDown() 134