source: python/trunk/Lib/distutils/tests/support.py

Last change on this file was 391, checked in by dmik, 11 years ago

python: Merge vendor 2.7.6 to trunk.

  • Property svn:eol-style set to native
File size: 6.8 KB
Line 
1"""Support code for distutils test cases."""
2import os
3import sys
4import shutil
5import tempfile
6import unittest
7import sysconfig
8from copy import deepcopy
9import warnings
10
11from distutils import log
12from distutils.log import DEBUG, INFO, WARN, ERROR, FATAL
13from distutils.core import Distribution
14
15
16def capture_warnings(func):
17 def _capture_warnings(*args, **kw):
18 with warnings.catch_warnings():
19 warnings.simplefilter("ignore")
20 return func(*args, **kw)
21 return _capture_warnings
22
23
24class LoggingSilencer(object):
25
26 def setUp(self):
27 super(LoggingSilencer, self).setUp()
28 self.threshold = log.set_threshold(log.FATAL)
29 # catching warnings
30 # when log will be replaced by logging
31 # we won't need such monkey-patch anymore
32 self._old_log = log.Log._log
33 log.Log._log = self._log
34 self.logs = []
35
36 def tearDown(self):
37 log.set_threshold(self.threshold)
38 log.Log._log = self._old_log
39 super(LoggingSilencer, self).tearDown()
40
41 def _log(self, level, msg, args):
42 if level not in (DEBUG, INFO, WARN, ERROR, FATAL):
43 raise ValueError('%s wrong log level' % str(level))
44 self.logs.append((level, msg, args))
45
46 def get_logs(self, *levels):
47 def _format(msg, args):
48 if len(args) == 0:
49 return msg
50 return msg % args
51 return [_format(msg, args) for level, msg, args
52 in self.logs if level in levels]
53
54 def clear_logs(self):
55 self.logs = []
56
57
58class TempdirManager(object):
59 """Mix-in class that handles temporary directories for test cases.
60
61 This is intended to be used with unittest.TestCase.
62 """
63
64 def setUp(self):
65 super(TempdirManager, self).setUp()
66 self.old_cwd = os.getcwd()
67 self.tempdirs = []
68
69 def tearDown(self):
70 # Restore working dir, for Solaris and derivatives, where rmdir()
71 # on the current directory fails.
72 os.chdir(self.old_cwd)
73 super(TempdirManager, self).tearDown()
74 while self.tempdirs:
75 d = self.tempdirs.pop()
76 shutil.rmtree(d, os.name in ('nt', 'cygwin'))
77
78 def mkdtemp(self):
79 """Create a temporary directory that will be cleaned up.
80
81 Returns the path of the directory.
82 """
83 d = tempfile.mkdtemp()
84 self.tempdirs.append(d)
85 return d
86
87 def write_file(self, path, content='xxx'):
88 """Writes a file in the given path.
89
90
91 path can be a string or a sequence.
92 """
93 if isinstance(path, (list, tuple)):
94 path = os.path.join(*path)
95 f = open(path, 'w')
96 try:
97 f.write(content)
98 finally:
99 f.close()
100
101 def create_dist(self, pkg_name='foo', **kw):
102 """Will generate a test environment.
103
104 This function creates:
105 - a Distribution instance using keywords
106 - a temporary directory with a package structure
107
108 It returns the package directory and the distribution
109 instance.
110 """
111 tmp_dir = self.mkdtemp()
112 pkg_dir = os.path.join(tmp_dir, pkg_name)
113 os.mkdir(pkg_dir)
114 dist = Distribution(attrs=kw)
115
116 return pkg_dir, dist
117
118
119class DummyCommand:
120 """Class to store options for retrieval via set_undefined_options()."""
121
122 def __init__(self, **kwargs):
123 for kw, val in kwargs.items():
124 setattr(self, kw, val)
125
126 def ensure_finalized(self):
127 pass
128
129
130class EnvironGuard(object):
131
132 def setUp(self):
133 super(EnvironGuard, self).setUp()
134 self.old_environ = deepcopy(os.environ)
135
136 def tearDown(self):
137 for key, value in self.old_environ.items():
138 if os.environ.get(key) != value:
139 os.environ[key] = value
140
141 for key in os.environ.keys():
142 if key not in self.old_environ:
143 del os.environ[key]
144
145 super(EnvironGuard, self).tearDown()
146
147
148def copy_xxmodule_c(directory):
149 """Helper for tests that need the xxmodule.c source file.
150
151 Example use:
152
153 def test_compile(self):
154 copy_xxmodule_c(self.tmpdir)
155 self.assertIn('xxmodule.c', os.listdir(self.tmpdir))
156
157 If the source file can be found, it will be copied to *directory*. If not,
158 the test will be skipped. Errors during copy are not caught.
159 """
160 filename = _get_xxmodule_path()
161 if filename is None:
162 raise unittest.SkipTest('cannot find xxmodule.c (test must run in '
163 'the python build dir)')
164 shutil.copy(filename, directory)
165
166
167def _get_xxmodule_path():
168 # FIXME when run from regrtest, srcdir seems to be '.', which does not help
169 # us find the xxmodule.c file
170 srcdir = sysconfig.get_config_var('srcdir')
171 candidates = [
172 # use installed copy if available
173 os.path.join(os.path.dirname(__file__), 'xxmodule.c'),
174 # otherwise try using copy from build directory
175 os.path.join(srcdir, 'Modules', 'xxmodule.c'),
176 # srcdir mysteriously can be $srcdir/Lib/distutils/tests when
177 # this file is run from its parent directory, so walk up the
178 # tree to find the real srcdir
179 os.path.join(srcdir, '..', '..', '..', 'Modules', 'xxmodule.c'),
180 ]
181 for path in candidates:
182 if os.path.exists(path):
183 return path
184
185
186def fixup_build_ext(cmd):
187 """Function needed to make build_ext tests pass.
188
189 When Python was build with --enable-shared on Unix, -L. is not good
190 enough to find the libpython<blah>.so. This is because regrtest runs
191 it under a tempdir, not in the top level where the .so lives. By the
192 time we've gotten here, Python's already been chdir'd to the tempdir.
193
194 When Python was built with in debug mode on Windows, build_ext commands
195 need their debug attribute set, and it is not done automatically for
196 some reason.
197
198 This function handles both of these things. Example use:
199
200 cmd = build_ext(dist)
201 support.fixup_build_ext(cmd)
202 cmd.ensure_finalized()
203
204 Unlike most other Unix platforms, Mac OS X embeds absolute paths
205 to shared libraries into executables, so the fixup is not needed there.
206 """
207 if os.name == 'nt':
208 cmd.debug = sys.executable.endswith('_d.exe')
209 elif sysconfig.get_config_var('Py_ENABLE_SHARED'):
210 # To further add to the shared builds fun on Unix, we can't just add
211 # library_dirs to the Extension() instance because that doesn't get
212 # plumbed through to the final compiler command.
213 runshared = sysconfig.get_config_var('RUNSHARED')
214 if runshared is None:
215 cmd.library_dirs = ['.']
216 else:
217 if sys.platform == 'darwin':
218 cmd.library_dirs = []
219 else:
220 name, equals, value = runshared.partition('=')
221 cmd.library_dirs = value.split(os.pathsep)
Note: See TracBrowser for help on using the repository browser.