OLD | NEW |
1 """Supporting definitions for the Python regression tests.""" | 1 """Supporting definitions for the Python regression tests.""" |
2 | 2 |
3 if __name__ != 'test.support': | 3 if __name__ != 'test.support': |
4 raise ImportError('support must be imported from the test package') | 4 raise ImportError('support must be imported from the test package') |
5 | 5 |
6 import contextlib | 6 import contextlib |
7 import errno | 7 import errno |
8 import functools | 8 import functools |
9 import gc | 9 import gc |
10 import socket | 10 import socket |
11 import sys | 11 import sys |
12 import os | 12 import os |
13 import platform | 13 import platform |
14 import shutil | 14 import shutil |
15 import warnings | 15 import warnings |
16 import unittest | 16 import unittest |
17 import importlib | 17 import importlib |
18 import collections | 18 import collections |
19 import re | 19 import re |
| 20 import imp |
20 | 21 |
21 __all__ = ["Error", "TestFailed", "ResourceDenied", "import_module", | 22 __all__ = [ |
22 "verbose", "use_resources", "max_memuse", "record_original_stdout", | 23 "Error", "TestFailed", "ResourceDenied", "import_module", |
23 "get_original_stdout", "unload", "unlink", "rmtree", "forget", | 24 "verbose", "use_resources", "max_memuse", "record_original_stdout", |
24 "is_resource_enabled", "requires", "find_unused_port", "bind_port", | 25 "get_original_stdout", "unload", "unlink", "rmtree", "forget", |
25 "fcmp", "is_jython", "TESTFN", "HOST", "FUZZ", "SAVEDCWD", "temp_cwd"
, | 26 "is_resource_enabled", "requires", "find_unused_port", "bind_port", |
26 "findfile", "sortdict", "check_syntax_error", "open_urlresource", | 27 "fcmp", "is_jython", "TESTFN", "HOST", "FUZZ", "SAVEDCWD", "temp_cwd", |
27 "check_warnings", "CleanImport", "EnvironmentVarGuard", | 28 "findfile", "sortdict", "check_syntax_error", "open_urlresource", |
28 "TransientResource", "captured_output", "captured_stdout", | 29 "check_warnings", "CleanImport", "EnvironmentVarGuard", |
29 "time_out", "socket_peer_reset", "ioerror_peer_reset", | 30 "TransientResource", "captured_output", "captured_stdout", |
30 "run_with_locale", | 31 "time_out", "socket_peer_reset", "ioerror_peer_reset", |
31 "set_memlimit", "bigmemtest", "bigaddrspacetest", "BasicTestRunner", | 32 "run_with_locale", 'temp_umask', |
32 "run_unittest", "run_doctest", "threading_setup", "threading_cleanup"
, | 33 "set_memlimit", "bigmemtest", "bigaddrspacetest", "BasicTestRunner", |
33 "reap_children", "cpython_only", "check_impl_detail", "get_attribute"
, | 34 "run_unittest", "run_doctest", "threading_setup", "threading_cleanup", |
34 "swap_item", "swap_attr"] | 35 "reap_children", "cpython_only", "check_impl_detail", "get_attribute", |
| 36 "swap_item", "swap_attr", |
| 37 ] |
35 | 38 |
36 | 39 |
37 class Error(Exception): | 40 class Error(Exception): |
38 """Base class for regression test exceptions.""" | 41 """Base class for regression test exceptions.""" |
39 | 42 |
40 class TestFailed(Error): | 43 class TestFailed(Error): |
41 """Test failed.""" | 44 """Test failed.""" |
42 | 45 |
43 class ResourceDenied(unittest.SkipTest): | 46 class ResourceDenied(unittest.SkipTest): |
44 """Test skipped because it requested a disallowed resource. | 47 """Test skipped because it requested a disallowed resource. |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
169 | 172 |
170 def unload(name): | 173 def unload(name): |
171 try: | 174 try: |
172 del sys.modules[name] | 175 del sys.modules[name] |
173 except KeyError: | 176 except KeyError: |
174 pass | 177 pass |
175 | 178 |
176 def unlink(filename): | 179 def unlink(filename): |
177 try: | 180 try: |
178 os.unlink(filename) | 181 os.unlink(filename) |
179 except OSError: | 182 except OSError as error: |
180 pass | 183 # The filename need not exist. |
| 184 if error.errno != errno.ENOENT: |
| 185 raise |
181 | 186 |
182 def rmtree(path): | 187 def rmtree(path): |
183 try: | 188 try: |
184 shutil.rmtree(path) | 189 shutil.rmtree(path) |
185 except OSError as e: | 190 except OSError as error: |
186 # Unix returns ENOENT, Windows returns ESRCH. | 191 # Unix returns ENOENT, Windows returns ESRCH. |
187 if e.errno not in (errno.ENOENT, errno.ESRCH): | 192 if error.errno not in (errno.ENOENT, errno.ESRCH): |
188 raise | 193 raise |
189 | 194 |
| 195 def make_legacy_pyc(source): |
| 196 """Move a PEP 3147 pyc/pyo file to its legacy pyc/pyo location. |
| 197 |
| 198 The choice of .pyc or .pyo extension is done based on the __debug__ flag |
| 199 value. |
| 200 |
| 201 :param source: The file system path to the source file. The source file |
| 202 does not need to exist, however the PEP 3147 pyc file must exist. |
| 203 :return: The file system path to the legacy pyc file. |
| 204 """ |
| 205 pyc_file = imp.cache_from_source(source) |
| 206 up_one = os.path.dirname(os.path.abspath(source)) |
| 207 legacy_pyc = os.path.join(up_one, source + ('c' if __debug__ else 'o')) |
| 208 os.rename(pyc_file, legacy_pyc) |
| 209 return legacy_pyc |
| 210 |
190 def forget(modname): | 211 def forget(modname): |
191 '''"Forget" a module was ever imported by removing it from sys.modules and | 212 """'Forget' a module was ever imported. |
192 deleting any .pyc and .pyo files.''' | 213 |
| 214 This removes the module from sys.modules and deletes any PEP 3147 or |
| 215 legacy .pyc and .pyo files. |
| 216 """ |
193 unload(modname) | 217 unload(modname) |
194 for dirname in sys.path: | 218 for dirname in sys.path: |
195 unlink(os.path.join(dirname, modname + '.pyc')) | 219 source = os.path.join(dirname, modname + '.py') |
196 # Deleting the .pyo file cannot be within the 'try' for the .pyc since | 220 # It doesn't matter if they exist or not, unlink all possible |
197 # the chance exists that there is no .pyc (and thus the 'try' statement | 221 # combinations of PEP 3147 and legacy pyc and pyo files. |
198 # is exited) but there is a .pyo file. | 222 unlink(source + 'c') |
199 unlink(os.path.join(dirname, modname + '.pyo')) | 223 unlink(source + 'o') |
| 224 unlink(imp.cache_from_source(source, force__debug__=True)) |
| 225 unlink(imp.cache_from_source(source, force__debug__=False)) |
200 | 226 |
201 def is_resource_enabled(resource): | 227 def is_resource_enabled(resource): |
202 """Test whether a resource is enabled. Known resources are set by | 228 """Test whether a resource is enabled. Known resources are set by |
203 regrtest.py.""" | 229 regrtest.py.""" |
204 return use_resources is not None and resource in use_resources | 230 return use_resources is not None and resource in use_resources |
205 | 231 |
206 def requires(resource, msg=None): | 232 def requires(resource, msg=None): |
207 """Raise ResourceDenied if the specified resource is not available. | 233 """Raise ResourceDenied if the specified resource is not available. |
208 | 234 |
209 If the caller's module is __main__ then automatically return True. The | 235 If the caller's module is __main__ then automatically return True. The |
210 possibility of False being returned occurs when regrtest.py is executing.""" | 236 possibility of False being returned occurs when regrtest.py is |
| 237 executing. |
| 238 """ |
211 # see if the caller's module is __main__ - if so, treat as if | 239 # see if the caller's module is __main__ - if so, treat as if |
212 # the resource was set | 240 # the resource was set |
213 if sys._getframe(1).f_globals.get("__name__") == "__main__": | 241 if sys._getframe(1).f_globals.get("__name__") == "__main__": |
214 return | 242 return |
215 if not is_resource_enabled(resource): | 243 if not is_resource_enabled(resource): |
216 if msg is None: | 244 if msg is None: |
217 msg = "Use of the `%s' resource not enabled" % resource | 245 msg = "Use of the `%s' resource not enabled" % resource |
218 raise ResourceDenied(msg) | 246 raise ResourceDenied(msg) |
219 | 247 |
220 HOST = 'localhost' | 248 HOST = 'localhost' |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 warnings.warn('tests may fail, unable to change the CWD to ' + name, | 425 warnings.warn('tests may fail, unable to change the CWD to ' + name, |
398 RuntimeWarning, stacklevel=3) | 426 RuntimeWarning, stacklevel=3) |
399 try: | 427 try: |
400 yield os.getcwd() | 428 yield os.getcwd() |
401 finally: | 429 finally: |
402 os.chdir(saved_dir) | 430 os.chdir(saved_dir) |
403 if is_temporary: | 431 if is_temporary: |
404 rmtree(name) | 432 rmtree(name) |
405 | 433 |
406 | 434 |
| 435 @contextlib.contextmanager |
| 436 def temp_umask(umask): |
| 437 """Context manager that temporarily sets the process umask.""" |
| 438 oldmask = os.umask(umask) |
| 439 try: |
| 440 yield |
| 441 finally: |
| 442 os.umask(oldmask) |
| 443 |
| 444 |
407 def findfile(file, here=__file__, subdir=None): | 445 def findfile(file, here=__file__, subdir=None): |
408 """Try to find a file on sys.path and the working directory. If it is not | 446 """Try to find a file on sys.path and the working directory. If it is not |
409 found the argument passed to the function is returned (this does not | 447 found the argument passed to the function is returned (this does not |
410 necessarily signal failure; could still be the legitimate path).""" | 448 necessarily signal failure; could still be the legitimate path).""" |
411 if os.path.isabs(file): | 449 if os.path.isabs(file): |
412 return file | 450 return file |
413 if subdir is not None: | 451 if subdir is not None: |
414 file = os.path.join(subdir, file) | 452 file = os.path.join(subdir, file) |
415 path = sys.path | 453 path = sys.path |
416 path = [os.path.dirname(here)] + path | 454 path = [os.path.dirname(here)] + path |
(...skipping 733 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1150 try: | 1188 try: |
1151 yield | 1189 yield |
1152 finally: | 1190 finally: |
1153 obj[item] = real_val | 1191 obj[item] = real_val |
1154 else: | 1192 else: |
1155 obj[item] = new_val | 1193 obj[item] = new_val |
1156 try: | 1194 try: |
1157 yield | 1195 yield |
1158 finally: | 1196 finally: |
1159 del obj[item] | 1197 del obj[item] |
OLD | NEW |