mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			209 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			209 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """Support code for distutils test cases."""
 | |
| import os
 | |
| import sys
 | |
| import shutil
 | |
| import tempfile
 | |
| import unittest
 | |
| import sysconfig
 | |
| from copy import deepcopy
 | |
| 
 | |
| from distutils import log
 | |
| from distutils.log import DEBUG, INFO, WARN, ERROR, FATAL
 | |
| from distutils.core import Distribution
 | |
| 
 | |
| 
 | |
| class LoggingSilencer(object):
 | |
| 
 | |
|     def setUp(self):
 | |
|         super().setUp()
 | |
|         self.threshold = log.set_threshold(log.FATAL)
 | |
|         # catching warnings
 | |
|         # when log will be replaced by logging
 | |
|         # we won't need such monkey-patch anymore
 | |
|         self._old_log = log.Log._log
 | |
|         log.Log._log = self._log
 | |
|         self.logs = []
 | |
| 
 | |
|     def tearDown(self):
 | |
|         log.set_threshold(self.threshold)
 | |
|         log.Log._log = self._old_log
 | |
|         super().tearDown()
 | |
| 
 | |
|     def _log(self, level, msg, args):
 | |
|         if level not in (DEBUG, INFO, WARN, ERROR, FATAL):
 | |
|             raise ValueError('%s wrong log level' % str(level))
 | |
|         self.logs.append((level, msg, args))
 | |
| 
 | |
|     def get_logs(self, *levels):
 | |
|         def _format(msg, args):
 | |
|             if len(args) == 0:
 | |
|                 return msg
 | |
|             return msg % args
 | |
|         return [_format(msg, args) for level, msg, args
 | |
|                 in self.logs if level in levels]
 | |
| 
 | |
|     def clear_logs(self):
 | |
|         self.logs = []
 | |
| 
 | |
| 
 | |
| class TempdirManager(object):
 | |
|     """Mix-in class that handles temporary directories for test cases.
 | |
| 
 | |
|     This is intended to be used with unittest.TestCase.
 | |
|     """
 | |
| 
 | |
|     def setUp(self):
 | |
|         super().setUp()
 | |
|         self.old_cwd = os.getcwd()
 | |
|         self.tempdirs = []
 | |
| 
 | |
|     def tearDown(self):
 | |
|         # Restore working dir, for Solaris and derivatives, where rmdir()
 | |
|         # on the current directory fails.
 | |
|         os.chdir(self.old_cwd)
 | |
|         super().tearDown()
 | |
|         while self.tempdirs:
 | |
|             d = self.tempdirs.pop()
 | |
|             shutil.rmtree(d, os.name in ('nt', 'cygwin'))
 | |
| 
 | |
|     def mkdtemp(self):
 | |
|         """Create a temporary directory that will be cleaned up.
 | |
| 
 | |
|         Returns the path of the directory.
 | |
|         """
 | |
|         d = tempfile.mkdtemp()
 | |
|         self.tempdirs.append(d)
 | |
|         return d
 | |
| 
 | |
|     def write_file(self, path, content='xxx'):
 | |
|         """Writes a file in the given path.
 | |
| 
 | |
| 
 | |
|         path can be a string or a sequence.
 | |
|         """
 | |
|         if isinstance(path, (list, tuple)):
 | |
|             path = os.path.join(*path)
 | |
|         f = open(path, 'w')
 | |
|         try:
 | |
|             f.write(content)
 | |
|         finally:
 | |
|             f.close()
 | |
| 
 | |
|     def create_dist(self, pkg_name='foo', **kw):
 | |
|         """Will generate a test environment.
 | |
| 
 | |
|         This function creates:
 | |
|          - a Distribution instance using keywords
 | |
|          - a temporary directory with a package structure
 | |
| 
 | |
|         It returns the package directory and the distribution
 | |
|         instance.
 | |
|         """
 | |
|         tmp_dir = self.mkdtemp()
 | |
|         pkg_dir = os.path.join(tmp_dir, pkg_name)
 | |
|         os.mkdir(pkg_dir)
 | |
|         dist = Distribution(attrs=kw)
 | |
| 
 | |
|         return pkg_dir, dist
 | |
| 
 | |
| 
 | |
| class DummyCommand:
 | |
|     """Class to store options for retrieval via set_undefined_options()."""
 | |
| 
 | |
|     def __init__(self, **kwargs):
 | |
|         for kw, val in kwargs.items():
 | |
|             setattr(self, kw, val)
 | |
| 
 | |
|     def ensure_finalized(self):
 | |
|         pass
 | |
| 
 | |
| 
 | |
| class EnvironGuard(object):
 | |
| 
 | |
|     def setUp(self):
 | |
|         super(EnvironGuard, self).setUp()
 | |
|         self.old_environ = deepcopy(os.environ)
 | |
| 
 | |
|     def tearDown(self):
 | |
|         for key, value in self.old_environ.items():
 | |
|             if os.environ.get(key) != value:
 | |
|                 os.environ[key] = value
 | |
| 
 | |
|         for key in tuple(os.environ.keys()):
 | |
|             if key not in self.old_environ:
 | |
|                 del os.environ[key]
 | |
| 
 | |
|         super(EnvironGuard, self).tearDown()
 | |
| 
 | |
| 
 | |
| def copy_xxmodule_c(directory):
 | |
|     """Helper for tests that need the xxmodule.c source file.
 | |
| 
 | |
|     Example use:
 | |
| 
 | |
|         def test_compile(self):
 | |
|             copy_xxmodule_c(self.tmpdir)
 | |
|             self.assertIn('xxmodule.c', os.listdir(self.tmpdir))
 | |
| 
 | |
|     If the source file can be found, it will be copied to *directory*.  If not,
 | |
|     the test will be skipped.  Errors during copy are not caught.
 | |
|     """
 | |
|     filename = _get_xxmodule_path()
 | |
|     if filename is None:
 | |
|         raise unittest.SkipTest('cannot find xxmodule.c (test must run in '
 | |
|                                 'the python build dir)')
 | |
|     shutil.copy(filename, directory)
 | |
| 
 | |
| 
 | |
| def _get_xxmodule_path():
 | |
|     srcdir = sysconfig.get_config_var('srcdir')
 | |
|     candidates = [
 | |
|         # use installed copy if available
 | |
|         os.path.join(os.path.dirname(__file__), 'xxmodule.c'),
 | |
|         # otherwise try using copy from build directory
 | |
|         os.path.join(srcdir, 'Modules', 'xxmodule.c'),
 | |
|         # srcdir mysteriously can be $srcdir/Lib/distutils/tests when
 | |
|         # this file is run from its parent directory, so walk up the
 | |
|         # tree to find the real srcdir
 | |
|         os.path.join(srcdir, '..', '..', '..', 'Modules', 'xxmodule.c'),
 | |
|     ]
 | |
|     for path in candidates:
 | |
|         if os.path.exists(path):
 | |
|             return path
 | |
| 
 | |
| 
 | |
| def fixup_build_ext(cmd):
 | |
|     """Function needed to make build_ext tests pass.
 | |
| 
 | |
|     When Python was built with --enable-shared on Unix, -L. is not enough to
 | |
|     find libpython<blah>.so, because regrtest runs in a tempdir, not in the
 | |
|     source directory where the .so lives.
 | |
| 
 | |
|     When Python was built with in debug mode on Windows, build_ext commands
 | |
|     need their debug attribute set, and it is not done automatically for
 | |
|     some reason.
 | |
| 
 | |
|     This function handles both of these things.  Example use:
 | |
| 
 | |
|         cmd = build_ext(dist)
 | |
|         support.fixup_build_ext(cmd)
 | |
|         cmd.ensure_finalized()
 | |
| 
 | |
|     Unlike most other Unix platforms, Mac OS X embeds absolute paths
 | |
|     to shared libraries into executables, so the fixup is not needed there.
 | |
|     """
 | |
|     if os.name == 'nt':
 | |
|         cmd.debug = sys.executable.endswith('_d.exe')
 | |
|     elif sysconfig.get_config_var('Py_ENABLE_SHARED'):
 | |
|         # To further add to the shared builds fun on Unix, we can't just add
 | |
|         # library_dirs to the Extension() instance because that doesn't get
 | |
|         # plumbed through to the final compiler command.
 | |
|         runshared = sysconfig.get_config_var('RUNSHARED')
 | |
|         if runshared is None:
 | |
|             cmd.library_dirs = ['.']
 | |
|         else:
 | |
|             if sys.platform == 'darwin':
 | |
|                 cmd.library_dirs = []
 | |
|             else:
 | |
|                 name, equals, value = runshared.partition('=')
 | |
|                 cmd.library_dirs = value.split(os.pathsep)
 | 
