python (3.11.7)

(root)/
lib/
python3.11/
distutils/
tests/
test_sysconfig.py
       1  """Tests for distutils.sysconfig."""
       2  import contextlib
       3  import os
       4  import shutil
       5  import subprocess
       6  import sys
       7  import textwrap
       8  import unittest
       9  
      10  from distutils import sysconfig
      11  from distutils.ccompiler import get_default_compiler
      12  from distutils.tests import support
      13  from test.support import swap_item, requires_subprocess, is_wasi
      14  from test.support.os_helper import TESTFN
      15  from test.support.warnings_helper import check_warnings
      16  
      17  
      18  class ESC[4;38;5;81mSysconfigTestCase(ESC[4;38;5;149msupportESC[4;38;5;149m.ESC[4;38;5;149mEnvironGuard, ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      19      def setUp(self):
      20          super(SysconfigTestCase, self).setUp()
      21          self.makefile = None
      22  
      23      def tearDown(self):
      24          if self.makefile is not None:
      25              os.unlink(self.makefile)
      26          self.cleanup_testfn()
      27          super(SysconfigTestCase, self).tearDown()
      28  
      29      def cleanup_testfn(self):
      30          if os.path.isfile(TESTFN):
      31              os.remove(TESTFN)
      32          elif os.path.isdir(TESTFN):
      33              shutil.rmtree(TESTFN)
      34  
      35      @unittest.skipIf(is_wasi, "Incompatible with WASI mapdir and OOT builds")
      36      def test_get_config_h_filename(self):
      37          config_h = sysconfig.get_config_h_filename()
      38          self.assertTrue(os.path.isfile(config_h), config_h)
      39  
      40      def test_get_python_lib(self):
      41          # XXX doesn't work on Linux when Python was never installed before
      42          #self.assertTrue(os.path.isdir(lib_dir), lib_dir)
      43          # test for pythonxx.lib?
      44          self.assertNotEqual(sysconfig.get_python_lib(),
      45                              sysconfig.get_python_lib(prefix=TESTFN))
      46  
      47      def test_get_config_vars(self):
      48          cvars = sysconfig.get_config_vars()
      49          self.assertIsInstance(cvars, dict)
      50          self.assertTrue(cvars)
      51  
      52      @unittest.skipIf(is_wasi, "Incompatible with WASI mapdir and OOT builds")
      53      def test_srcdir(self):
      54          # See Issues #15322, #15364.
      55          srcdir = sysconfig.get_config_var('srcdir')
      56  
      57          self.assertTrue(os.path.isabs(srcdir), srcdir)
      58          self.assertTrue(os.path.isdir(srcdir), srcdir)
      59  
      60          if sysconfig.python_build:
      61              # The python executable has not been installed so srcdir
      62              # should be a full source checkout.
      63              Python_h = os.path.join(srcdir, 'Include', 'Python.h')
      64              self.assertTrue(os.path.exists(Python_h), Python_h)
      65              # <srcdir>/PC/pyconfig.h always exists even if unused on POSIX.
      66              pyconfig_h = os.path.join(srcdir, 'PC', 'pyconfig.h')
      67              self.assertTrue(os.path.exists(pyconfig_h), pyconfig_h)
      68              pyconfig_h_in = os.path.join(srcdir, 'pyconfig.h.in')
      69              self.assertTrue(os.path.exists(pyconfig_h_in), pyconfig_h_in)
      70          elif os.name == 'posix':
      71              self.assertEqual(
      72                  os.path.dirname(sysconfig.get_makefile_filename()),
      73                  srcdir)
      74  
      75      def test_srcdir_independent_of_cwd(self):
      76          # srcdir should be independent of the current working directory
      77          # See Issues #15322, #15364.
      78          srcdir = sysconfig.get_config_var('srcdir')
      79          cwd = os.getcwd()
      80          try:
      81              os.chdir('..')
      82              srcdir2 = sysconfig.get_config_var('srcdir')
      83          finally:
      84              os.chdir(cwd)
      85          self.assertEqual(srcdir, srcdir2)
      86  
      87      def customize_compiler(self):
      88          # make sure AR gets caught
      89          class ESC[4;38;5;81mcompiler:
      90              compiler_type = 'unix'
      91  
      92              def set_executables(self, **kw):
      93                  self.exes = kw
      94  
      95          sysconfig_vars = {
      96              'AR': 'sc_ar',
      97              'CC': 'sc_cc',
      98              'CXX': 'sc_cxx',
      99              'ARFLAGS': '--sc-arflags',
     100              'CFLAGS': '--sc-cflags',
     101              'CCSHARED': '--sc-ccshared',
     102              'LDSHARED': 'sc_ldshared',
     103              'SHLIB_SUFFIX': 'sc_shutil_suffix',
     104  
     105              # On macOS, disable _osx_support.customize_compiler()
     106              'CUSTOMIZED_OSX_COMPILER': 'True',
     107          }
     108  
     109          comp = compiler()
     110          with contextlib.ExitStack() as cm:
     111              for key, value in sysconfig_vars.items():
     112                  cm.enter_context(swap_item(sysconfig._config_vars, key, value))
     113              sysconfig.customize_compiler(comp)
     114  
     115          return comp
     116  
     117      @unittest.skipUnless(get_default_compiler() == 'unix',
     118                           'not testing if default compiler is not unix')
     119      def test_customize_compiler(self):
     120          # Make sure that sysconfig._config_vars is initialized
     121          sysconfig.get_config_vars()
     122  
     123          os.environ['AR'] = 'env_ar'
     124          os.environ['CC'] = 'env_cc'
     125          os.environ['CPP'] = 'env_cpp'
     126          os.environ['CXX'] = 'env_cxx --env-cxx-flags'
     127          os.environ['LDSHARED'] = 'env_ldshared'
     128          os.environ['LDFLAGS'] = '--env-ldflags'
     129          os.environ['ARFLAGS'] = '--env-arflags'
     130          os.environ['CFLAGS'] = '--env-cflags'
     131          os.environ['CPPFLAGS'] = '--env-cppflags'
     132  
     133          comp = self.customize_compiler()
     134          self.assertEqual(comp.exes['archiver'],
     135                           'env_ar --env-arflags')
     136          self.assertEqual(comp.exes['preprocessor'],
     137                           'env_cpp --env-cppflags')
     138          self.assertEqual(comp.exes['compiler'],
     139                           'env_cc --sc-cflags --env-cflags --env-cppflags')
     140          self.assertEqual(comp.exes['compiler_so'],
     141                           ('env_cc --sc-cflags '
     142                            '--env-cflags ''--env-cppflags --sc-ccshared'))
     143          self.assertEqual(comp.exes['compiler_cxx'],
     144                           'env_cxx --env-cxx-flags')
     145          self.assertEqual(comp.exes['linker_exe'],
     146                           'env_cc')
     147          self.assertEqual(comp.exes['linker_so'],
     148                           ('env_ldshared --env-ldflags --env-cflags'
     149                            ' --env-cppflags'))
     150          self.assertEqual(comp.shared_lib_extension, 'sc_shutil_suffix')
     151  
     152          del os.environ['AR']
     153          del os.environ['CC']
     154          del os.environ['CPP']
     155          del os.environ['CXX']
     156          del os.environ['LDSHARED']
     157          del os.environ['LDFLAGS']
     158          del os.environ['ARFLAGS']
     159          del os.environ['CFLAGS']
     160          del os.environ['CPPFLAGS']
     161  
     162          comp = self.customize_compiler()
     163          self.assertEqual(comp.exes['archiver'],
     164                           'sc_ar --sc-arflags')
     165          self.assertEqual(comp.exes['preprocessor'],
     166                           'sc_cc -E')
     167          self.assertEqual(comp.exes['compiler'],
     168                           'sc_cc --sc-cflags')
     169          self.assertEqual(comp.exes['compiler_so'],
     170                           'sc_cc --sc-cflags --sc-ccshared')
     171          self.assertEqual(comp.exes['compiler_cxx'],
     172                           'sc_cxx')
     173          self.assertEqual(comp.exes['linker_exe'],
     174                           'sc_cc')
     175          self.assertEqual(comp.exes['linker_so'],
     176                           'sc_ldshared')
     177          self.assertEqual(comp.shared_lib_extension, 'sc_shutil_suffix')
     178  
     179      def test_parse_makefile_base(self):
     180          self.makefile = TESTFN
     181          fd = open(self.makefile, 'w')
     182          try:
     183              fd.write(r"CONFIG_ARGS=  '--arg1=optarg1' 'ENV=LIB'" '\n')
     184              fd.write('VAR=$OTHER\nOTHER=foo')
     185          finally:
     186              fd.close()
     187          d = sysconfig.parse_makefile(self.makefile)
     188          self.assertEqual(d, {'CONFIG_ARGS': "'--arg1=optarg1' 'ENV=LIB'",
     189                               'OTHER': 'foo'})
     190  
     191      def test_parse_makefile_literal_dollar(self):
     192          self.makefile = TESTFN
     193          fd = open(self.makefile, 'w')
     194          try:
     195              fd.write(r"CONFIG_ARGS=  '--arg1=optarg1' 'ENV=\$$LIB'" '\n')
     196              fd.write('VAR=$OTHER\nOTHER=foo')
     197          finally:
     198              fd.close()
     199          d = sysconfig.parse_makefile(self.makefile)
     200          self.assertEqual(d, {'CONFIG_ARGS': r"'--arg1=optarg1' 'ENV=\$LIB'",
     201                               'OTHER': 'foo'})
     202  
     203  
     204      def test_sysconfig_module(self):
     205          import sysconfig as global_sysconfig
     206          self.assertEqual(global_sysconfig.get_config_var('CFLAGS'),
     207                           sysconfig.get_config_var('CFLAGS'))
     208          self.assertEqual(global_sysconfig.get_config_var('LDFLAGS'),
     209                           sysconfig.get_config_var('LDFLAGS'))
     210  
     211      @unittest.skipIf(sysconfig.get_config_var('CUSTOMIZED_OSX_COMPILER'),
     212                       'compiler flags customized')
     213      def test_sysconfig_compiler_vars(self):
     214          # On OS X, binary installers support extension module building on
     215          # various levels of the operating system with differing Xcode
     216          # configurations.  This requires customization of some of the
     217          # compiler configuration directives to suit the environment on
     218          # the installed machine.  Some of these customizations may require
     219          # running external programs and, so, are deferred until needed by
     220          # the first extension module build.  With Python 3.3, only
     221          # the Distutils version of sysconfig is used for extension module
     222          # builds, which happens earlier in the Distutils tests.  This may
     223          # cause the following tests to fail since no tests have caused
     224          # the global version of sysconfig to call the customization yet.
     225          # The solution for now is to simply skip this test in this case.
     226          # The longer-term solution is to only have one version of sysconfig.
     227  
     228          import sysconfig as global_sysconfig
     229          if sysconfig.get_config_var('CUSTOMIZED_OSX_COMPILER'):
     230              self.skipTest('compiler flags customized')
     231          self.assertEqual(global_sysconfig.get_config_var('LDSHARED'),
     232                           sysconfig.get_config_var('LDSHARED'))
     233          self.assertEqual(global_sysconfig.get_config_var('CC'),
     234                           sysconfig.get_config_var('CC'))
     235  
     236      @requires_subprocess()
     237      def test_customize_compiler_before_get_config_vars(self):
     238          # Issue #21923: test that a Distribution compiler
     239          # instance can be called without an explicit call to
     240          # get_config_vars().
     241          with open(TESTFN, 'w') as f:
     242              f.writelines(textwrap.dedent('''\
     243                  from distutils.core import Distribution
     244                  config = Distribution().get_command_obj('config')
     245                  # try_compile may pass or it may fail if no compiler
     246                  # is found but it should not raise an exception.
     247                  rc = config.try_compile('int x;')
     248                  '''))
     249          p = subprocess.Popen([str(sys.executable), TESTFN],
     250                  stdout=subprocess.PIPE,
     251                  stderr=subprocess.STDOUT,
     252                  universal_newlines=True)
     253          outs, errs = p.communicate()
     254          self.assertEqual(0, p.returncode, "Subprocess failed: " + outs)
     255  
     256  
     257  if __name__ == '__main__':
     258      unittest.main()