blob: 49277111bfae05e89dc8c70364a8076345eb9af3 [file] [log] [blame]
Fred Drakeb8ab8b62004-06-17 20:14:50 +00001"""Support code for distutils test cases."""
Tarek Ziadéc1375d52009-02-14 14:35:51 +00002import os
Fred Drakeb8ab8b62004-06-17 20:14:50 +00003import shutil
4import tempfile
Éric Araujodef15da2011-08-20 06:27:18 +02005import unittest
6import sysconfig
Tarek Ziadé430fb632009-10-18 11:34:51 +00007from copy import deepcopy
Fred Drakeb8ab8b62004-06-17 20:14:50 +00008
Fred Drakeedcac8f2004-08-03 18:53:07 +00009from distutils import log
Tarek Ziadé31d46072009-09-21 13:55:19 +000010from distutils.log import DEBUG, INFO, WARN, ERROR, FATAL
Tarek Ziadébaf51802009-03-31 21:37:16 +000011from distutils.core import Distribution
Fred Drakeedcac8f2004-08-03 18:53:07 +000012
Éric Araujodef15da2011-08-20 06:27:18 +020013
Fred Drakeedcac8f2004-08-03 18:53:07 +000014class LoggingSilencer(object):
15
16 def setUp(self):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000017 super().setUp()
Fred Drakeedcac8f2004-08-03 18:53:07 +000018 self.threshold = log.set_threshold(log.FATAL)
Tarek Ziadé5af55c62009-05-16 16:52:13 +000019 # catching warnings
20 # when log will be replaced by logging
21 # we won't need such monkey-patch anymore
22 self._old_log = log.Log._log
23 log.Log._log = self._log
24 self.logs = []
Fred Drakeedcac8f2004-08-03 18:53:07 +000025
26 def tearDown(self):
27 log.set_threshold(self.threshold)
Tarek Ziadé5af55c62009-05-16 16:52:13 +000028 log.Log._log = self._old_log
Guido van Rossumcd16bf62007-06-13 18:07:49 +000029 super().tearDown()
Fred Drakeedcac8f2004-08-03 18:53:07 +000030
Tarek Ziadé5af55c62009-05-16 16:52:13 +000031 def _log(self, level, msg, args):
Tarek Ziadé31d46072009-09-21 13:55:19 +000032 if level not in (DEBUG, INFO, WARN, ERROR, FATAL):
33 raise ValueError('%s wrong log level' % str(level))
Tarek Ziadé5af55c62009-05-16 16:52:13 +000034 self.logs.append((level, msg, args))
35
36 def get_logs(self, *levels):
37 def _format(msg, args):
38 if len(args) == 0:
39 return msg
40 return msg % args
41 return [_format(msg, args) for level, msg, args
42 in self.logs if level in levels]
43
44 def clear_logs(self):
45 self.logs = []
Fred Drakeb8ab8b62004-06-17 20:14:50 +000046
Éric Araujodef15da2011-08-20 06:27:18 +020047
Fred Drakeb8ab8b62004-06-17 20:14:50 +000048class TempdirManager(object):
49 """Mix-in class that handles temporary directories for test cases.
50
51 This is intended to be used with unittest.TestCase.
52 """
53
54 def setUp(self):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000055 super().setUp()
Fred Drakeb8ab8b62004-06-17 20:14:50 +000056 self.tempdirs = []
57
58 def tearDown(self):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000059 super().tearDown()
Fred Drakeb8ab8b62004-06-17 20:14:50 +000060 while self.tempdirs:
61 d = self.tempdirs.pop()
Tarek Ziadéc1375d52009-02-14 14:35:51 +000062 shutil.rmtree(d, os.name in ('nt', 'cygwin'))
Fred Drakeb8ab8b62004-06-17 20:14:50 +000063
64 def mkdtemp(self):
65 """Create a temporary directory that will be cleaned up.
66
67 Returns the path of the directory.
68 """
69 d = tempfile.mkdtemp()
70 self.tempdirs.append(d)
71 return d
72
Tarek Ziadébaf51802009-03-31 21:37:16 +000073 def write_file(self, path, content='xxx'):
Tarek Ziadé0d0506e2009-02-16 21:49:12 +000074 """Writes a file in the given path.
75
76
77 path can be a string or a sequence.
78 """
79 if isinstance(path, (list, tuple)):
80 path = os.path.join(*path)
81 f = open(path, 'w')
82 try:
83 f.write(content)
84 finally:
85 f.close()
Fred Drakeb8ab8b62004-06-17 20:14:50 +000086
Tarek Ziadébaf51802009-03-31 21:37:16 +000087 def create_dist(self, pkg_name='foo', **kw):
88 """Will generate a test environment.
89
90 This function creates:
91 - a Distribution instance using keywords
92 - a temporary directory with a package structure
93
94 It returns the package directory and the distribution
95 instance.
96 """
97 tmp_dir = self.mkdtemp()
98 pkg_dir = os.path.join(tmp_dir, pkg_name)
99 os.mkdir(pkg_dir)
100 dist = Distribution(attrs=kw)
101
102 return pkg_dir, dist
103
Éric Araujodef15da2011-08-20 06:27:18 +0200104
Fred Drakeb8ab8b62004-06-17 20:14:50 +0000105class DummyCommand:
106 """Class to store options for retrieval via set_undefined_options()."""
107
108 def __init__(self, **kwargs):
109 for kw, val in kwargs.items():
110 setattr(self, kw, val)
111
112 def ensure_finalized(self):
113 pass
Tarek Ziadé29bbb962009-05-10 12:02:35 +0000114
Éric Araujodef15da2011-08-20 06:27:18 +0200115
Tarek Ziadé29bbb962009-05-10 12:02:35 +0000116class EnvironGuard(object):
117
118 def setUp(self):
119 super(EnvironGuard, self).setUp()
Tarek Ziadé430fb632009-10-18 11:34:51 +0000120 self.old_environ = deepcopy(os.environ)
Tarek Ziadé29bbb962009-05-10 12:02:35 +0000121
122 def tearDown(self):
Tarek Ziadé430fb632009-10-18 11:34:51 +0000123 for key, value in self.old_environ.items():
124 if os.environ.get(key) != value:
125 os.environ[key] = value
126
127 for key in tuple(os.environ.keys()):
128 if key not in self.old_environ:
129 del os.environ[key]
130
Tarek Ziadé29bbb962009-05-10 12:02:35 +0000131 super(EnvironGuard, self).tearDown()
Éric Araujodef15da2011-08-20 06:27:18 +0200132
133
134def copy_xxmodule_c(directory):
135 """Helper for tests that need the xxmodule.c source file.
136
137 Example use:
138
Éric Araujoe1e13312011-08-20 07:25:39 +0200139 def test_compile(self):
140 copy_xxmodule_c(self.tmpdir)
Éric Araujo52b201f2011-08-21 12:53:37 +0200141 self.assertIn('xxmodule.c', os.listdir(self.tmpdir))
Éric Araujodef15da2011-08-20 06:27:18 +0200142
143 If the source file can be found, it will be copied to *directory*. If not,
144 the test will be skipped. Errors during copy are not caught.
145 """
146 filename = _get_xxmodule_path()
147 if filename is None:
148 raise unittest.SkipTest('cannot find xxmodule.c (test must run in '
149 'the python build dir)')
150 shutil.copy(filename, directory)
151
152
153def _get_xxmodule_path():
154 srcdir = sysconfig.get_config_var('srcdir')
155 candidates = [
156 # use installed copy if available
157 os.path.join(os.path.dirname(__file__), 'xxmodule.c'),
158 # otherwise try using copy from build directory
159 os.path.join(srcdir, 'Modules', 'xxmodule.c'),
160 # srcdir mysteriously can be $srcdir/Lib/distutils/tests when
161 # this file is run from its parent directory, so walk up the
162 # tree to find the real srcdir
163 os.path.join(srcdir, '..', '..', '..', 'Modules', 'xxmodule.c'),
164 ]
165 for path in candidates:
166 if os.path.exists(path):
167 return path