17db96d56Sopenharmony_ci"""
27db96d56Sopenharmony_ciTest harness for the venv module.
37db96d56Sopenharmony_ci
47db96d56Sopenharmony_ciCopyright (C) 2011-2012 Vinay Sajip.
57db96d56Sopenharmony_ciLicensed to the PSF under a contributor agreement.
67db96d56Sopenharmony_ci"""
77db96d56Sopenharmony_ci
87db96d56Sopenharmony_ciimport contextlib
97db96d56Sopenharmony_ciimport ensurepip
107db96d56Sopenharmony_ciimport os
117db96d56Sopenharmony_ciimport os.path
127db96d56Sopenharmony_ciimport pathlib
137db96d56Sopenharmony_ciimport re
147db96d56Sopenharmony_ciimport shutil
157db96d56Sopenharmony_ciimport struct
167db96d56Sopenharmony_ciimport subprocess
177db96d56Sopenharmony_ciimport sys
187db96d56Sopenharmony_ciimport sysconfig
197db96d56Sopenharmony_ciimport tempfile
207db96d56Sopenharmony_cifrom test.support import (captured_stdout, captured_stderr, requires_zlib,
217db96d56Sopenharmony_ci                          skip_if_broken_multiprocessing_synchronize, verbose,
227db96d56Sopenharmony_ci                          requires_subprocess, is_emscripten, is_wasi,
237db96d56Sopenharmony_ci                          requires_venv_with_pip, TEST_HOME_DIR)
247db96d56Sopenharmony_cifrom test.support.os_helper import (can_symlink, EnvironmentVarGuard, rmtree)
257db96d56Sopenharmony_ciimport unittest
267db96d56Sopenharmony_ciimport venv
277db96d56Sopenharmony_cifrom unittest.mock import patch, Mock
287db96d56Sopenharmony_ci
297db96d56Sopenharmony_citry:
307db96d56Sopenharmony_ci    import ctypes
317db96d56Sopenharmony_ciexcept ImportError:
327db96d56Sopenharmony_ci    ctypes = None
337db96d56Sopenharmony_ci
347db96d56Sopenharmony_ci# Platforms that set sys._base_executable can create venvs from within
357db96d56Sopenharmony_ci# another venv, so no need to skip tests that require venv.create().
367db96d56Sopenharmony_cirequireVenvCreate = unittest.skipUnless(
377db96d56Sopenharmony_ci    sys.prefix == sys.base_prefix
387db96d56Sopenharmony_ci    or sys._base_executable != sys.executable,
397db96d56Sopenharmony_ci    'cannot run venv.create from within a venv on this platform')
407db96d56Sopenharmony_ci
417db96d56Sopenharmony_ciif is_emscripten or is_wasi:
427db96d56Sopenharmony_ci    raise unittest.SkipTest("venv is not available on Emscripten/WASI.")
437db96d56Sopenharmony_ci
447db96d56Sopenharmony_ci@requires_subprocess()
457db96d56Sopenharmony_cidef check_output(cmd, encoding=None):
467db96d56Sopenharmony_ci    p = subprocess.Popen(cmd,
477db96d56Sopenharmony_ci        stdout=subprocess.PIPE,
487db96d56Sopenharmony_ci        stderr=subprocess.PIPE,
497db96d56Sopenharmony_ci        encoding=encoding)
507db96d56Sopenharmony_ci    out, err = p.communicate()
517db96d56Sopenharmony_ci    if p.returncode:
527db96d56Sopenharmony_ci        if verbose and err:
537db96d56Sopenharmony_ci            print(err.decode('utf-8', 'backslashreplace'))
547db96d56Sopenharmony_ci        raise subprocess.CalledProcessError(
557db96d56Sopenharmony_ci            p.returncode, cmd, out, err)
567db96d56Sopenharmony_ci    return out, err
577db96d56Sopenharmony_ci
587db96d56Sopenharmony_ciclass BaseTest(unittest.TestCase):
597db96d56Sopenharmony_ci    """Base class for venv tests."""
607db96d56Sopenharmony_ci    maxDiff = 80 * 50
617db96d56Sopenharmony_ci
627db96d56Sopenharmony_ci    def setUp(self):
637db96d56Sopenharmony_ci        self.env_dir = os.path.realpath(tempfile.mkdtemp())
647db96d56Sopenharmony_ci        if os.name == 'nt':
657db96d56Sopenharmony_ci            self.bindir = 'Scripts'
667db96d56Sopenharmony_ci            self.lib = ('Lib',)
677db96d56Sopenharmony_ci            self.include = 'Include'
687db96d56Sopenharmony_ci        else:
697db96d56Sopenharmony_ci            self.bindir = 'bin'
707db96d56Sopenharmony_ci            self.lib = ('lib', 'python%d.%d' % sys.version_info[:2])
717db96d56Sopenharmony_ci            self.include = 'include'
727db96d56Sopenharmony_ci        executable = sys._base_executable
737db96d56Sopenharmony_ci        self.exe = os.path.split(executable)[-1]
747db96d56Sopenharmony_ci        if (sys.platform == 'win32'
757db96d56Sopenharmony_ci            and os.path.lexists(executable)
767db96d56Sopenharmony_ci            and not os.path.exists(executable)):
777db96d56Sopenharmony_ci            self.cannot_link_exe = True
787db96d56Sopenharmony_ci        else:
797db96d56Sopenharmony_ci            self.cannot_link_exe = False
807db96d56Sopenharmony_ci
817db96d56Sopenharmony_ci    def tearDown(self):
827db96d56Sopenharmony_ci        rmtree(self.env_dir)
837db96d56Sopenharmony_ci
847db96d56Sopenharmony_ci    def run_with_capture(self, func, *args, **kwargs):
857db96d56Sopenharmony_ci        with captured_stdout() as output:
867db96d56Sopenharmony_ci            with captured_stderr() as error:
877db96d56Sopenharmony_ci                func(*args, **kwargs)
887db96d56Sopenharmony_ci        return output.getvalue(), error.getvalue()
897db96d56Sopenharmony_ci
907db96d56Sopenharmony_ci    def get_env_file(self, *args):
917db96d56Sopenharmony_ci        return os.path.join(self.env_dir, *args)
927db96d56Sopenharmony_ci
937db96d56Sopenharmony_ci    def get_text_file_contents(self, *args, encoding='utf-8'):
947db96d56Sopenharmony_ci        with open(self.get_env_file(*args), 'r', encoding=encoding) as f:
957db96d56Sopenharmony_ci            result = f.read()
967db96d56Sopenharmony_ci        return result
977db96d56Sopenharmony_ci
987db96d56Sopenharmony_ciclass BasicTest(BaseTest):
997db96d56Sopenharmony_ci    """Test venv module functionality."""
1007db96d56Sopenharmony_ci
1017db96d56Sopenharmony_ci    def isdir(self, *args):
1027db96d56Sopenharmony_ci        fn = self.get_env_file(*args)
1037db96d56Sopenharmony_ci        self.assertTrue(os.path.isdir(fn))
1047db96d56Sopenharmony_ci
1057db96d56Sopenharmony_ci    def test_defaults_with_str_path(self):
1067db96d56Sopenharmony_ci        """
1077db96d56Sopenharmony_ci        Test the create function with default arguments and a str path.
1087db96d56Sopenharmony_ci        """
1097db96d56Sopenharmony_ci        rmtree(self.env_dir)
1107db96d56Sopenharmony_ci        self.run_with_capture(venv.create, self.env_dir)
1117db96d56Sopenharmony_ci        self._check_output_of_default_create()
1127db96d56Sopenharmony_ci
1137db96d56Sopenharmony_ci    def test_defaults_with_pathlib_path(self):
1147db96d56Sopenharmony_ci        """
1157db96d56Sopenharmony_ci        Test the create function with default arguments and a pathlib.Path path.
1167db96d56Sopenharmony_ci        """
1177db96d56Sopenharmony_ci        rmtree(self.env_dir)
1187db96d56Sopenharmony_ci        self.run_with_capture(venv.create, pathlib.Path(self.env_dir))
1197db96d56Sopenharmony_ci        self._check_output_of_default_create()
1207db96d56Sopenharmony_ci
1217db96d56Sopenharmony_ci    def _check_output_of_default_create(self):
1227db96d56Sopenharmony_ci        self.isdir(self.bindir)
1237db96d56Sopenharmony_ci        self.isdir(self.include)
1247db96d56Sopenharmony_ci        self.isdir(*self.lib)
1257db96d56Sopenharmony_ci        # Issue 21197
1267db96d56Sopenharmony_ci        p = self.get_env_file('lib64')
1277db96d56Sopenharmony_ci        conditions = ((struct.calcsize('P') == 8) and (os.name == 'posix') and
1287db96d56Sopenharmony_ci                      (sys.platform != 'darwin'))
1297db96d56Sopenharmony_ci        if conditions:
1307db96d56Sopenharmony_ci            self.assertTrue(os.path.islink(p))
1317db96d56Sopenharmony_ci        else:
1327db96d56Sopenharmony_ci            self.assertFalse(os.path.exists(p))
1337db96d56Sopenharmony_ci        data = self.get_text_file_contents('pyvenv.cfg')
1347db96d56Sopenharmony_ci        executable = sys._base_executable
1357db96d56Sopenharmony_ci        path = os.path.dirname(executable)
1367db96d56Sopenharmony_ci        self.assertIn('home = %s' % path, data)
1377db96d56Sopenharmony_ci        self.assertIn('executable = %s' %
1387db96d56Sopenharmony_ci                      os.path.realpath(sys.executable), data)
1397db96d56Sopenharmony_ci        copies = '' if os.name=='nt' else ' --copies'
1407db96d56Sopenharmony_ci        cmd = f'command = {sys.executable} -m venv{copies} --without-pip {self.env_dir}'
1417db96d56Sopenharmony_ci        self.assertIn(cmd, data)
1427db96d56Sopenharmony_ci        fn = self.get_env_file(self.bindir, self.exe)
1437db96d56Sopenharmony_ci        if not os.path.exists(fn):  # diagnostics for Windows buildbot failures
1447db96d56Sopenharmony_ci            bd = self.get_env_file(self.bindir)
1457db96d56Sopenharmony_ci            print('Contents of %r:' % bd)
1467db96d56Sopenharmony_ci            print('    %r' % os.listdir(bd))
1477db96d56Sopenharmony_ci        self.assertTrue(os.path.exists(fn), 'File %r should exist.' % fn)
1487db96d56Sopenharmony_ci
1497db96d56Sopenharmony_ci    def test_config_file_command_key(self):
1507db96d56Sopenharmony_ci        attrs = [
1517db96d56Sopenharmony_ci            (None, None),
1527db96d56Sopenharmony_ci            ('symlinks', '--copies'),
1537db96d56Sopenharmony_ci            ('with_pip', '--without-pip'),
1547db96d56Sopenharmony_ci            ('system_site_packages', '--system-site-packages'),
1557db96d56Sopenharmony_ci            ('clear', '--clear'),
1567db96d56Sopenharmony_ci            ('upgrade', '--upgrade'),
1577db96d56Sopenharmony_ci            ('upgrade_deps', '--upgrade-deps'),
1587db96d56Sopenharmony_ci            ('prompt', '--prompt'),
1597db96d56Sopenharmony_ci        ]
1607db96d56Sopenharmony_ci        for attr, opt in attrs:
1617db96d56Sopenharmony_ci            rmtree(self.env_dir)
1627db96d56Sopenharmony_ci            if not attr:
1637db96d56Sopenharmony_ci                b = venv.EnvBuilder()
1647db96d56Sopenharmony_ci            else:
1657db96d56Sopenharmony_ci                b = venv.EnvBuilder(
1667db96d56Sopenharmony_ci                    **{attr: False if attr in ('with_pip', 'symlinks') else True})
1677db96d56Sopenharmony_ci            b.upgrade_dependencies = Mock() # avoid pip command to upgrade deps
1687db96d56Sopenharmony_ci            b._setup_pip = Mock() # avoid pip setup
1697db96d56Sopenharmony_ci            self.run_with_capture(b.create, self.env_dir)
1707db96d56Sopenharmony_ci            data = self.get_text_file_contents('pyvenv.cfg')
1717db96d56Sopenharmony_ci            if not attr:
1727db96d56Sopenharmony_ci                for opt in ('--system-site-packages', '--clear', '--upgrade',
1737db96d56Sopenharmony_ci                        '--upgrade-deps', '--prompt'):
1747db96d56Sopenharmony_ci                    self.assertNotRegex(data, rf'command = .* {opt}')
1757db96d56Sopenharmony_ci            elif os.name=='nt' and attr=='symlinks':
1767db96d56Sopenharmony_ci                pass
1777db96d56Sopenharmony_ci            else:
1787db96d56Sopenharmony_ci                self.assertRegex(data, rf'command = .* {opt}')
1797db96d56Sopenharmony_ci
1807db96d56Sopenharmony_ci    def test_prompt(self):
1817db96d56Sopenharmony_ci        env_name = os.path.split(self.env_dir)[1]
1827db96d56Sopenharmony_ci
1837db96d56Sopenharmony_ci        rmtree(self.env_dir)
1847db96d56Sopenharmony_ci        builder = venv.EnvBuilder()
1857db96d56Sopenharmony_ci        self.run_with_capture(builder.create, self.env_dir)
1867db96d56Sopenharmony_ci        context = builder.ensure_directories(self.env_dir)
1877db96d56Sopenharmony_ci        data = self.get_text_file_contents('pyvenv.cfg')
1887db96d56Sopenharmony_ci        self.assertEqual(context.prompt, '(%s) ' % env_name)
1897db96d56Sopenharmony_ci        self.assertNotIn("prompt = ", data)
1907db96d56Sopenharmony_ci
1917db96d56Sopenharmony_ci        rmtree(self.env_dir)
1927db96d56Sopenharmony_ci        builder = venv.EnvBuilder(prompt='My prompt')
1937db96d56Sopenharmony_ci        self.run_with_capture(builder.create, self.env_dir)
1947db96d56Sopenharmony_ci        context = builder.ensure_directories(self.env_dir)
1957db96d56Sopenharmony_ci        data = self.get_text_file_contents('pyvenv.cfg')
1967db96d56Sopenharmony_ci        self.assertEqual(context.prompt, '(My prompt) ')
1977db96d56Sopenharmony_ci        self.assertIn("prompt = 'My prompt'\n", data)
1987db96d56Sopenharmony_ci
1997db96d56Sopenharmony_ci        rmtree(self.env_dir)
2007db96d56Sopenharmony_ci        builder = venv.EnvBuilder(prompt='.')
2017db96d56Sopenharmony_ci        cwd = os.path.basename(os.getcwd())
2027db96d56Sopenharmony_ci        self.run_with_capture(builder.create, self.env_dir)
2037db96d56Sopenharmony_ci        context = builder.ensure_directories(self.env_dir)
2047db96d56Sopenharmony_ci        data = self.get_text_file_contents('pyvenv.cfg')
2057db96d56Sopenharmony_ci        self.assertEqual(context.prompt, '(%s) ' % cwd)
2067db96d56Sopenharmony_ci        self.assertIn("prompt = '%s'\n" % cwd, data)
2077db96d56Sopenharmony_ci
2087db96d56Sopenharmony_ci    def test_upgrade_dependencies(self):
2097db96d56Sopenharmony_ci        builder = venv.EnvBuilder()
2107db96d56Sopenharmony_ci        bin_path = 'Scripts' if sys.platform == 'win32' else 'bin'
2117db96d56Sopenharmony_ci        python_exe = os.path.split(sys.executable)[1]
2127db96d56Sopenharmony_ci        with tempfile.TemporaryDirectory() as fake_env_dir:
2137db96d56Sopenharmony_ci            expect_exe = os.path.normcase(
2147db96d56Sopenharmony_ci                os.path.join(fake_env_dir, bin_path, python_exe)
2157db96d56Sopenharmony_ci            )
2167db96d56Sopenharmony_ci            if sys.platform == 'win32':
2177db96d56Sopenharmony_ci                expect_exe = os.path.normcase(os.path.realpath(expect_exe))
2187db96d56Sopenharmony_ci
2197db96d56Sopenharmony_ci            def pip_cmd_checker(cmd, **kwargs):
2207db96d56Sopenharmony_ci                cmd[0] = os.path.normcase(cmd[0])
2217db96d56Sopenharmony_ci                self.assertEqual(
2227db96d56Sopenharmony_ci                    cmd,
2237db96d56Sopenharmony_ci                    [
2247db96d56Sopenharmony_ci                        expect_exe,
2257db96d56Sopenharmony_ci                        '-m',
2267db96d56Sopenharmony_ci                        'pip',
2277db96d56Sopenharmony_ci                        'install',
2287db96d56Sopenharmony_ci                        '--upgrade',
2297db96d56Sopenharmony_ci                        'pip',
2307db96d56Sopenharmony_ci                        'setuptools'
2317db96d56Sopenharmony_ci                    ]
2327db96d56Sopenharmony_ci                )
2337db96d56Sopenharmony_ci
2347db96d56Sopenharmony_ci            fake_context = builder.ensure_directories(fake_env_dir)
2357db96d56Sopenharmony_ci            with patch('venv.subprocess.check_output', pip_cmd_checker):
2367db96d56Sopenharmony_ci                builder.upgrade_dependencies(fake_context)
2377db96d56Sopenharmony_ci
2387db96d56Sopenharmony_ci    @requireVenvCreate
2397db96d56Sopenharmony_ci    def test_prefixes(self):
2407db96d56Sopenharmony_ci        """
2417db96d56Sopenharmony_ci        Test that the prefix values are as expected.
2427db96d56Sopenharmony_ci        """
2437db96d56Sopenharmony_ci        # check a venv's prefixes
2447db96d56Sopenharmony_ci        rmtree(self.env_dir)
2457db96d56Sopenharmony_ci        self.run_with_capture(venv.create, self.env_dir)
2467db96d56Sopenharmony_ci        envpy = os.path.join(self.env_dir, self.bindir, self.exe)
2477db96d56Sopenharmony_ci        cmd = [envpy, '-c', None]
2487db96d56Sopenharmony_ci        for prefix, expected in (
2497db96d56Sopenharmony_ci            ('prefix', self.env_dir),
2507db96d56Sopenharmony_ci            ('exec_prefix', self.env_dir),
2517db96d56Sopenharmony_ci            ('base_prefix', sys.base_prefix),
2527db96d56Sopenharmony_ci            ('base_exec_prefix', sys.base_exec_prefix)):
2537db96d56Sopenharmony_ci            cmd[2] = 'import sys; print(sys.%s)' % prefix
2547db96d56Sopenharmony_ci            out, err = check_output(cmd)
2557db96d56Sopenharmony_ci            self.assertEqual(out.strip(), expected.encode(), prefix)
2567db96d56Sopenharmony_ci
2577db96d56Sopenharmony_ci    @requireVenvCreate
2587db96d56Sopenharmony_ci    def test_sysconfig(self):
2597db96d56Sopenharmony_ci        """
2607db96d56Sopenharmony_ci        Test that the sysconfig functions work in a virtual environment.
2617db96d56Sopenharmony_ci        """
2627db96d56Sopenharmony_ci        rmtree(self.env_dir)
2637db96d56Sopenharmony_ci        self.run_with_capture(venv.create, self.env_dir, symlinks=False)
2647db96d56Sopenharmony_ci        envpy = os.path.join(self.env_dir, self.bindir, self.exe)
2657db96d56Sopenharmony_ci        cmd = [envpy, '-c', None]
2667db96d56Sopenharmony_ci        for call, expected in (
2677db96d56Sopenharmony_ci            # installation scheme
2687db96d56Sopenharmony_ci            ('get_preferred_scheme("prefix")', 'venv'),
2697db96d56Sopenharmony_ci            ('get_default_scheme()', 'venv'),
2707db96d56Sopenharmony_ci            # build environment
2717db96d56Sopenharmony_ci            ('is_python_build()', str(sysconfig.is_python_build())),
2727db96d56Sopenharmony_ci            ('get_makefile_filename()', sysconfig.get_makefile_filename()),
2737db96d56Sopenharmony_ci            ('get_config_h_filename()', sysconfig.get_config_h_filename())):
2747db96d56Sopenharmony_ci            with self.subTest(call):
2757db96d56Sopenharmony_ci                cmd[2] = 'import sysconfig; print(sysconfig.%s)' % call
2767db96d56Sopenharmony_ci                out, err = check_output(cmd)
2777db96d56Sopenharmony_ci                self.assertEqual(out.strip(), expected.encode(), err)
2787db96d56Sopenharmony_ci
2797db96d56Sopenharmony_ci    @requireVenvCreate
2807db96d56Sopenharmony_ci    @unittest.skipUnless(can_symlink(), 'Needs symlinks')
2817db96d56Sopenharmony_ci    def test_sysconfig_symlinks(self):
2827db96d56Sopenharmony_ci        """
2837db96d56Sopenharmony_ci        Test that the sysconfig functions work in a virtual environment.
2847db96d56Sopenharmony_ci        """
2857db96d56Sopenharmony_ci        rmtree(self.env_dir)
2867db96d56Sopenharmony_ci        self.run_with_capture(venv.create, self.env_dir, symlinks=True)
2877db96d56Sopenharmony_ci        envpy = os.path.join(self.env_dir, self.bindir, self.exe)
2887db96d56Sopenharmony_ci        cmd = [envpy, '-c', None]
2897db96d56Sopenharmony_ci        for call, expected in (
2907db96d56Sopenharmony_ci            # installation scheme
2917db96d56Sopenharmony_ci            ('get_preferred_scheme("prefix")', 'venv'),
2927db96d56Sopenharmony_ci            ('get_default_scheme()', 'venv'),
2937db96d56Sopenharmony_ci            # build environment
2947db96d56Sopenharmony_ci            ('is_python_build()', str(sysconfig.is_python_build())),
2957db96d56Sopenharmony_ci            ('get_makefile_filename()', sysconfig.get_makefile_filename()),
2967db96d56Sopenharmony_ci            ('get_config_h_filename()', sysconfig.get_config_h_filename())):
2977db96d56Sopenharmony_ci            with self.subTest(call):
2987db96d56Sopenharmony_ci                cmd[2] = 'import sysconfig; print(sysconfig.%s)' % call
2997db96d56Sopenharmony_ci                out, err = check_output(cmd)
3007db96d56Sopenharmony_ci                self.assertEqual(out.strip(), expected.encode(), err)
3017db96d56Sopenharmony_ci
3027db96d56Sopenharmony_ci    if sys.platform == 'win32':
3037db96d56Sopenharmony_ci        ENV_SUBDIRS = (
3047db96d56Sopenharmony_ci            ('Scripts',),
3057db96d56Sopenharmony_ci            ('Include',),
3067db96d56Sopenharmony_ci            ('Lib',),
3077db96d56Sopenharmony_ci            ('Lib', 'site-packages'),
3087db96d56Sopenharmony_ci        )
3097db96d56Sopenharmony_ci    else:
3107db96d56Sopenharmony_ci        ENV_SUBDIRS = (
3117db96d56Sopenharmony_ci            ('bin',),
3127db96d56Sopenharmony_ci            ('include',),
3137db96d56Sopenharmony_ci            ('lib',),
3147db96d56Sopenharmony_ci            ('lib', 'python%d.%d' % sys.version_info[:2]),
3157db96d56Sopenharmony_ci            ('lib', 'python%d.%d' % sys.version_info[:2], 'site-packages'),
3167db96d56Sopenharmony_ci        )
3177db96d56Sopenharmony_ci
3187db96d56Sopenharmony_ci    def create_contents(self, paths, filename):
3197db96d56Sopenharmony_ci        """
3207db96d56Sopenharmony_ci        Create some files in the environment which are unrelated
3217db96d56Sopenharmony_ci        to the virtual environment.
3227db96d56Sopenharmony_ci        """
3237db96d56Sopenharmony_ci        for subdirs in paths:
3247db96d56Sopenharmony_ci            d = os.path.join(self.env_dir, *subdirs)
3257db96d56Sopenharmony_ci            os.mkdir(d)
3267db96d56Sopenharmony_ci            fn = os.path.join(d, filename)
3277db96d56Sopenharmony_ci            with open(fn, 'wb') as f:
3287db96d56Sopenharmony_ci                f.write(b'Still here?')
3297db96d56Sopenharmony_ci
3307db96d56Sopenharmony_ci    def test_overwrite_existing(self):
3317db96d56Sopenharmony_ci        """
3327db96d56Sopenharmony_ci        Test creating environment in an existing directory.
3337db96d56Sopenharmony_ci        """
3347db96d56Sopenharmony_ci        self.create_contents(self.ENV_SUBDIRS, 'foo')
3357db96d56Sopenharmony_ci        venv.create(self.env_dir)
3367db96d56Sopenharmony_ci        for subdirs in self.ENV_SUBDIRS:
3377db96d56Sopenharmony_ci            fn = os.path.join(self.env_dir, *(subdirs + ('foo',)))
3387db96d56Sopenharmony_ci            self.assertTrue(os.path.exists(fn))
3397db96d56Sopenharmony_ci            with open(fn, 'rb') as f:
3407db96d56Sopenharmony_ci                self.assertEqual(f.read(), b'Still here?')
3417db96d56Sopenharmony_ci
3427db96d56Sopenharmony_ci        builder = venv.EnvBuilder(clear=True)
3437db96d56Sopenharmony_ci        builder.create(self.env_dir)
3447db96d56Sopenharmony_ci        for subdirs in self.ENV_SUBDIRS:
3457db96d56Sopenharmony_ci            fn = os.path.join(self.env_dir, *(subdirs + ('foo',)))
3467db96d56Sopenharmony_ci            self.assertFalse(os.path.exists(fn))
3477db96d56Sopenharmony_ci
3487db96d56Sopenharmony_ci    def clear_directory(self, path):
3497db96d56Sopenharmony_ci        for fn in os.listdir(path):
3507db96d56Sopenharmony_ci            fn = os.path.join(path, fn)
3517db96d56Sopenharmony_ci            if os.path.islink(fn) or os.path.isfile(fn):
3527db96d56Sopenharmony_ci                os.remove(fn)
3537db96d56Sopenharmony_ci            elif os.path.isdir(fn):
3547db96d56Sopenharmony_ci                rmtree(fn)
3557db96d56Sopenharmony_ci
3567db96d56Sopenharmony_ci    def test_unoverwritable_fails(self):
3577db96d56Sopenharmony_ci        #create a file clashing with directories in the env dir
3587db96d56Sopenharmony_ci        for paths in self.ENV_SUBDIRS[:3]:
3597db96d56Sopenharmony_ci            fn = os.path.join(self.env_dir, *paths)
3607db96d56Sopenharmony_ci            with open(fn, 'wb') as f:
3617db96d56Sopenharmony_ci                f.write(b'')
3627db96d56Sopenharmony_ci            self.assertRaises((ValueError, OSError), venv.create, self.env_dir)
3637db96d56Sopenharmony_ci            self.clear_directory(self.env_dir)
3647db96d56Sopenharmony_ci
3657db96d56Sopenharmony_ci    def test_upgrade(self):
3667db96d56Sopenharmony_ci        """
3677db96d56Sopenharmony_ci        Test upgrading an existing environment directory.
3687db96d56Sopenharmony_ci        """
3697db96d56Sopenharmony_ci        # See Issue #21643: the loop needs to run twice to ensure
3707db96d56Sopenharmony_ci        # that everything works on the upgrade (the first run just creates
3717db96d56Sopenharmony_ci        # the venv).
3727db96d56Sopenharmony_ci        for upgrade in (False, True):
3737db96d56Sopenharmony_ci            builder = venv.EnvBuilder(upgrade=upgrade)
3747db96d56Sopenharmony_ci            self.run_with_capture(builder.create, self.env_dir)
3757db96d56Sopenharmony_ci            self.isdir(self.bindir)
3767db96d56Sopenharmony_ci            self.isdir(self.include)
3777db96d56Sopenharmony_ci            self.isdir(*self.lib)
3787db96d56Sopenharmony_ci            fn = self.get_env_file(self.bindir, self.exe)
3797db96d56Sopenharmony_ci            if not os.path.exists(fn):
3807db96d56Sopenharmony_ci                # diagnostics for Windows buildbot failures
3817db96d56Sopenharmony_ci                bd = self.get_env_file(self.bindir)
3827db96d56Sopenharmony_ci                print('Contents of %r:' % bd)
3837db96d56Sopenharmony_ci                print('    %r' % os.listdir(bd))
3847db96d56Sopenharmony_ci            self.assertTrue(os.path.exists(fn), 'File %r should exist.' % fn)
3857db96d56Sopenharmony_ci
3867db96d56Sopenharmony_ci    def test_isolation(self):
3877db96d56Sopenharmony_ci        """
3887db96d56Sopenharmony_ci        Test isolation from system site-packages
3897db96d56Sopenharmony_ci        """
3907db96d56Sopenharmony_ci        for ssp, s in ((True, 'true'), (False, 'false')):
3917db96d56Sopenharmony_ci            builder = venv.EnvBuilder(clear=True, system_site_packages=ssp)
3927db96d56Sopenharmony_ci            builder.create(self.env_dir)
3937db96d56Sopenharmony_ci            data = self.get_text_file_contents('pyvenv.cfg')
3947db96d56Sopenharmony_ci            self.assertIn('include-system-site-packages = %s\n' % s, data)
3957db96d56Sopenharmony_ci
3967db96d56Sopenharmony_ci    @unittest.skipUnless(can_symlink(), 'Needs symlinks')
3977db96d56Sopenharmony_ci    def test_symlinking(self):
3987db96d56Sopenharmony_ci        """
3997db96d56Sopenharmony_ci        Test symlinking works as expected
4007db96d56Sopenharmony_ci        """
4017db96d56Sopenharmony_ci        for usl in (False, True):
4027db96d56Sopenharmony_ci            builder = venv.EnvBuilder(clear=True, symlinks=usl)
4037db96d56Sopenharmony_ci            builder.create(self.env_dir)
4047db96d56Sopenharmony_ci            fn = self.get_env_file(self.bindir, self.exe)
4057db96d56Sopenharmony_ci            # Don't test when False, because e.g. 'python' is always
4067db96d56Sopenharmony_ci            # symlinked to 'python3.3' in the env, even when symlinking in
4077db96d56Sopenharmony_ci            # general isn't wanted.
4087db96d56Sopenharmony_ci            if usl:
4097db96d56Sopenharmony_ci                if self.cannot_link_exe:
4107db96d56Sopenharmony_ci                    # Symlinking is skipped when our executable is already a
4117db96d56Sopenharmony_ci                    # special app symlink
4127db96d56Sopenharmony_ci                    self.assertFalse(os.path.islink(fn))
4137db96d56Sopenharmony_ci                else:
4147db96d56Sopenharmony_ci                    self.assertTrue(os.path.islink(fn))
4157db96d56Sopenharmony_ci
4167db96d56Sopenharmony_ci    # If a venv is created from a source build and that venv is used to
4177db96d56Sopenharmony_ci    # run the test, the pyvenv.cfg in the venv created in the test will
4187db96d56Sopenharmony_ci    # point to the venv being used to run the test, and we lose the link
4197db96d56Sopenharmony_ci    # to the source build - so Python can't initialise properly.
4207db96d56Sopenharmony_ci    @requireVenvCreate
4217db96d56Sopenharmony_ci    def test_executable(self):
4227db96d56Sopenharmony_ci        """
4237db96d56Sopenharmony_ci        Test that the sys.executable value is as expected.
4247db96d56Sopenharmony_ci        """
4257db96d56Sopenharmony_ci        rmtree(self.env_dir)
4267db96d56Sopenharmony_ci        self.run_with_capture(venv.create, self.env_dir)
4277db96d56Sopenharmony_ci        envpy = os.path.join(os.path.realpath(self.env_dir),
4287db96d56Sopenharmony_ci                             self.bindir, self.exe)
4297db96d56Sopenharmony_ci        out, err = check_output([envpy, '-c',
4307db96d56Sopenharmony_ci            'import sys; print(sys.executable)'])
4317db96d56Sopenharmony_ci        self.assertEqual(out.strip(), envpy.encode())
4327db96d56Sopenharmony_ci
4337db96d56Sopenharmony_ci    @unittest.skipUnless(can_symlink(), 'Needs symlinks')
4347db96d56Sopenharmony_ci    def test_executable_symlinks(self):
4357db96d56Sopenharmony_ci        """
4367db96d56Sopenharmony_ci        Test that the sys.executable value is as expected.
4377db96d56Sopenharmony_ci        """
4387db96d56Sopenharmony_ci        rmtree(self.env_dir)
4397db96d56Sopenharmony_ci        builder = venv.EnvBuilder(clear=True, symlinks=True)
4407db96d56Sopenharmony_ci        builder.create(self.env_dir)
4417db96d56Sopenharmony_ci        envpy = os.path.join(os.path.realpath(self.env_dir),
4427db96d56Sopenharmony_ci                             self.bindir, self.exe)
4437db96d56Sopenharmony_ci        out, err = check_output([envpy, '-c',
4447db96d56Sopenharmony_ci            'import sys; print(sys.executable)'])
4457db96d56Sopenharmony_ci        self.assertEqual(out.strip(), envpy.encode())
4467db96d56Sopenharmony_ci
4477db96d56Sopenharmony_ci    @unittest.skipUnless(os.name == 'nt', 'only relevant on Windows')
4487db96d56Sopenharmony_ci    def test_unicode_in_batch_file(self):
4497db96d56Sopenharmony_ci        """
4507db96d56Sopenharmony_ci        Test handling of Unicode paths
4517db96d56Sopenharmony_ci        """
4527db96d56Sopenharmony_ci        rmtree(self.env_dir)
4537db96d56Sopenharmony_ci        env_dir = os.path.join(os.path.realpath(self.env_dir), 'ϼўТλФЙ')
4547db96d56Sopenharmony_ci        builder = venv.EnvBuilder(clear=True)
4557db96d56Sopenharmony_ci        builder.create(env_dir)
4567db96d56Sopenharmony_ci        activate = os.path.join(env_dir, self.bindir, 'activate.bat')
4577db96d56Sopenharmony_ci        envpy = os.path.join(env_dir, self.bindir, self.exe)
4587db96d56Sopenharmony_ci        out, err = check_output(
4597db96d56Sopenharmony_ci            [activate, '&', self.exe, '-c', 'print(0)'],
4607db96d56Sopenharmony_ci            encoding='oem',
4617db96d56Sopenharmony_ci        )
4627db96d56Sopenharmony_ci        self.assertEqual(out.strip(), '0')
4637db96d56Sopenharmony_ci
4647db96d56Sopenharmony_ci    @requireVenvCreate
4657db96d56Sopenharmony_ci    def test_multiprocessing(self):
4667db96d56Sopenharmony_ci        """
4677db96d56Sopenharmony_ci        Test that the multiprocessing is able to spawn.
4687db96d56Sopenharmony_ci        """
4697db96d56Sopenharmony_ci        # bpo-36342: Instantiation of a Pool object imports the
4707db96d56Sopenharmony_ci        # multiprocessing.synchronize module. Skip the test if this module
4717db96d56Sopenharmony_ci        # cannot be imported.
4727db96d56Sopenharmony_ci        skip_if_broken_multiprocessing_synchronize()
4737db96d56Sopenharmony_ci
4747db96d56Sopenharmony_ci        rmtree(self.env_dir)
4757db96d56Sopenharmony_ci        self.run_with_capture(venv.create, self.env_dir)
4767db96d56Sopenharmony_ci        envpy = os.path.join(os.path.realpath(self.env_dir),
4777db96d56Sopenharmony_ci                             self.bindir, self.exe)
4787db96d56Sopenharmony_ci        out, err = check_output([envpy, '-c',
4797db96d56Sopenharmony_ci            'from multiprocessing import Pool; '
4807db96d56Sopenharmony_ci            'pool = Pool(1); '
4817db96d56Sopenharmony_ci            'print(pool.apply_async("Python".lower).get(3)); '
4827db96d56Sopenharmony_ci            'pool.terminate()'])
4837db96d56Sopenharmony_ci        self.assertEqual(out.strip(), "python".encode())
4847db96d56Sopenharmony_ci
4857db96d56Sopenharmony_ci    @requireVenvCreate
4867db96d56Sopenharmony_ci    def test_multiprocessing_recursion(self):
4877db96d56Sopenharmony_ci        """
4887db96d56Sopenharmony_ci        Test that the multiprocessing is able to spawn itself
4897db96d56Sopenharmony_ci        """
4907db96d56Sopenharmony_ci        skip_if_broken_multiprocessing_synchronize()
4917db96d56Sopenharmony_ci
4927db96d56Sopenharmony_ci        rmtree(self.env_dir)
4937db96d56Sopenharmony_ci        self.run_with_capture(venv.create, self.env_dir)
4947db96d56Sopenharmony_ci        envpy = os.path.join(os.path.realpath(self.env_dir),
4957db96d56Sopenharmony_ci                             self.bindir, self.exe)
4967db96d56Sopenharmony_ci        script = os.path.join(TEST_HOME_DIR, '_test_venv_multiprocessing.py')
4977db96d56Sopenharmony_ci        subprocess.check_call([envpy, script])
4987db96d56Sopenharmony_ci
4997db96d56Sopenharmony_ci    @unittest.skipIf(os.name == 'nt', 'not relevant on Windows')
5007db96d56Sopenharmony_ci    def test_deactivate_with_strict_bash_opts(self):
5017db96d56Sopenharmony_ci        bash = shutil.which("bash")
5027db96d56Sopenharmony_ci        if bash is None:
5037db96d56Sopenharmony_ci            self.skipTest("bash required for this test")
5047db96d56Sopenharmony_ci        rmtree(self.env_dir)
5057db96d56Sopenharmony_ci        builder = venv.EnvBuilder(clear=True)
5067db96d56Sopenharmony_ci        builder.create(self.env_dir)
5077db96d56Sopenharmony_ci        activate = os.path.join(self.env_dir, self.bindir, "activate")
5087db96d56Sopenharmony_ci        test_script = os.path.join(self.env_dir, "test_strict.sh")
5097db96d56Sopenharmony_ci        with open(test_script, "w") as f:
5107db96d56Sopenharmony_ci            f.write("set -euo pipefail\n"
5117db96d56Sopenharmony_ci                    f"source {activate}\n"
5127db96d56Sopenharmony_ci                    "deactivate\n")
5137db96d56Sopenharmony_ci        out, err = check_output([bash, test_script])
5147db96d56Sopenharmony_ci        self.assertEqual(out, "".encode())
5157db96d56Sopenharmony_ci        self.assertEqual(err, "".encode())
5167db96d56Sopenharmony_ci
5177db96d56Sopenharmony_ci
5187db96d56Sopenharmony_ci    @unittest.skipUnless(sys.platform == 'darwin', 'only relevant on macOS')
5197db96d56Sopenharmony_ci    def test_macos_env(self):
5207db96d56Sopenharmony_ci        rmtree(self.env_dir)
5217db96d56Sopenharmony_ci        builder = venv.EnvBuilder()
5227db96d56Sopenharmony_ci        builder.create(self.env_dir)
5237db96d56Sopenharmony_ci
5247db96d56Sopenharmony_ci        envpy = os.path.join(os.path.realpath(self.env_dir),
5257db96d56Sopenharmony_ci                             self.bindir, self.exe)
5267db96d56Sopenharmony_ci        out, err = check_output([envpy, '-c',
5277db96d56Sopenharmony_ci            'import os; print("__PYVENV_LAUNCHER__" in os.environ)'])
5287db96d56Sopenharmony_ci        self.assertEqual(out.strip(), 'False'.encode())
5297db96d56Sopenharmony_ci
5307db96d56Sopenharmony_ci    def test_pathsep_error(self):
5317db96d56Sopenharmony_ci        """
5327db96d56Sopenharmony_ci        Test that venv creation fails when the target directory contains
5337db96d56Sopenharmony_ci        the path separator.
5347db96d56Sopenharmony_ci        """
5357db96d56Sopenharmony_ci        rmtree(self.env_dir)
5367db96d56Sopenharmony_ci        bad_itempath = self.env_dir + os.pathsep
5377db96d56Sopenharmony_ci        self.assertRaises(ValueError, venv.create, bad_itempath)
5387db96d56Sopenharmony_ci        self.assertRaises(ValueError, venv.create, pathlib.Path(bad_itempath))
5397db96d56Sopenharmony_ci
5407db96d56Sopenharmony_ci    @unittest.skipIf(os.name == 'nt', 'not relevant on Windows')
5417db96d56Sopenharmony_ci    @requireVenvCreate
5427db96d56Sopenharmony_ci    def test_zippath_from_non_installed_posix(self):
5437db96d56Sopenharmony_ci        """
5447db96d56Sopenharmony_ci        Test that when create venv from non-installed python, the zip path
5457db96d56Sopenharmony_ci        value is as expected.
5467db96d56Sopenharmony_ci        """
5477db96d56Sopenharmony_ci        rmtree(self.env_dir)
5487db96d56Sopenharmony_ci        # First try to create a non-installed python. It's not a real full
5497db96d56Sopenharmony_ci        # functional non-installed python, but enough for this test.
5507db96d56Sopenharmony_ci        platlibdir = sys.platlibdir
5517db96d56Sopenharmony_ci        non_installed_dir = os.path.realpath(tempfile.mkdtemp())
5527db96d56Sopenharmony_ci        self.addCleanup(rmtree, non_installed_dir)
5537db96d56Sopenharmony_ci        bindir = os.path.join(non_installed_dir, self.bindir)
5547db96d56Sopenharmony_ci        os.mkdir(bindir)
5557db96d56Sopenharmony_ci        shutil.copy2(sys.executable, bindir)
5567db96d56Sopenharmony_ci        libdir = os.path.join(non_installed_dir, platlibdir, self.lib[1])
5577db96d56Sopenharmony_ci        os.makedirs(libdir)
5587db96d56Sopenharmony_ci        landmark = os.path.join(libdir, "os.py")
5597db96d56Sopenharmony_ci        stdlib_zip = "python%d%d.zip" % sys.version_info[:2]
5607db96d56Sopenharmony_ci        zip_landmark = os.path.join(non_installed_dir,
5617db96d56Sopenharmony_ci                                    platlibdir,
5627db96d56Sopenharmony_ci                                    stdlib_zip)
5637db96d56Sopenharmony_ci        additional_pythonpath_for_non_installed = []
5647db96d56Sopenharmony_ci        # Copy stdlib files to the non-installed python so venv can
5657db96d56Sopenharmony_ci        # correctly calculate the prefix.
5667db96d56Sopenharmony_ci        for eachpath in sys.path:
5677db96d56Sopenharmony_ci            if eachpath.endswith(".zip"):
5687db96d56Sopenharmony_ci                if os.path.isfile(eachpath):
5697db96d56Sopenharmony_ci                    shutil.copyfile(
5707db96d56Sopenharmony_ci                        eachpath,
5717db96d56Sopenharmony_ci                        os.path.join(non_installed_dir, platlibdir))
5727db96d56Sopenharmony_ci            elif os.path.isfile(os.path.join(eachpath, "os.py")):
5737db96d56Sopenharmony_ci                for name in os.listdir(eachpath):
5747db96d56Sopenharmony_ci                    if name == "site-packages":
5757db96d56Sopenharmony_ci                        continue
5767db96d56Sopenharmony_ci                    fn = os.path.join(eachpath, name)
5777db96d56Sopenharmony_ci                    if os.path.isfile(fn):
5787db96d56Sopenharmony_ci                        shutil.copy(fn, libdir)
5797db96d56Sopenharmony_ci                    elif os.path.isdir(fn):
5807db96d56Sopenharmony_ci                        shutil.copytree(fn, os.path.join(libdir, name))
5817db96d56Sopenharmony_ci            else:
5827db96d56Sopenharmony_ci                additional_pythonpath_for_non_installed.append(
5837db96d56Sopenharmony_ci                    eachpath)
5847db96d56Sopenharmony_ci        cmd = [os.path.join(non_installed_dir, self.bindir, self.exe),
5857db96d56Sopenharmony_ci               "-m",
5867db96d56Sopenharmony_ci               "venv",
5877db96d56Sopenharmony_ci               "--without-pip",
5887db96d56Sopenharmony_ci               self.env_dir]
5897db96d56Sopenharmony_ci        # Our fake non-installed python is not fully functional because
5907db96d56Sopenharmony_ci        # it cannot find the extensions. Set PYTHONPATH so it can run the
5917db96d56Sopenharmony_ci        # venv module correctly.
5927db96d56Sopenharmony_ci        pythonpath = os.pathsep.join(
5937db96d56Sopenharmony_ci            additional_pythonpath_for_non_installed)
5947db96d56Sopenharmony_ci        # For python built with shared enabled. We need to set
5957db96d56Sopenharmony_ci        # LD_LIBRARY_PATH so the non-installed python can find and link
5967db96d56Sopenharmony_ci        # libpython.so
5977db96d56Sopenharmony_ci        ld_library_path = sysconfig.get_config_var("LIBDIR")
5987db96d56Sopenharmony_ci        if not ld_library_path or sysconfig.is_python_build():
5997db96d56Sopenharmony_ci            ld_library_path = os.path.abspath(os.path.dirname(sys.executable))
6007db96d56Sopenharmony_ci        if sys.platform == 'darwin':
6017db96d56Sopenharmony_ci            ld_library_path_env = "DYLD_LIBRARY_PATH"
6027db96d56Sopenharmony_ci        else:
6037db96d56Sopenharmony_ci            ld_library_path_env = "LD_LIBRARY_PATH"
6047db96d56Sopenharmony_ci        subprocess.check_call(cmd,
6057db96d56Sopenharmony_ci                              env={"PYTHONPATH": pythonpath,
6067db96d56Sopenharmony_ci                                   ld_library_path_env: ld_library_path})
6077db96d56Sopenharmony_ci        envpy = os.path.join(self.env_dir, self.bindir, self.exe)
6087db96d56Sopenharmony_ci        # Now check the venv created from the non-installed python has
6097db96d56Sopenharmony_ci        # correct zip path in pythonpath.
6107db96d56Sopenharmony_ci        cmd = [envpy, '-S', '-c', 'import sys; print(sys.path)']
6117db96d56Sopenharmony_ci        out, err = check_output(cmd)
6127db96d56Sopenharmony_ci        self.assertTrue(zip_landmark.encode() in out)
6137db96d56Sopenharmony_ci
6147db96d56Sopenharmony_ci@requireVenvCreate
6157db96d56Sopenharmony_ciclass EnsurePipTest(BaseTest):
6167db96d56Sopenharmony_ci    """Test venv module installation of pip."""
6177db96d56Sopenharmony_ci    def assert_pip_not_installed(self):
6187db96d56Sopenharmony_ci        envpy = os.path.join(os.path.realpath(self.env_dir),
6197db96d56Sopenharmony_ci                             self.bindir, self.exe)
6207db96d56Sopenharmony_ci        out, err = check_output([envpy, '-c',
6217db96d56Sopenharmony_ci            'try:\n import pip\nexcept ImportError:\n print("OK")'])
6227db96d56Sopenharmony_ci        # We force everything to text, so unittest gives the detailed diff
6237db96d56Sopenharmony_ci        # if we get unexpected results
6247db96d56Sopenharmony_ci        err = err.decode("latin-1") # Force to text, prevent decoding errors
6257db96d56Sopenharmony_ci        self.assertEqual(err, "")
6267db96d56Sopenharmony_ci        out = out.decode("latin-1") # Force to text, prevent decoding errors
6277db96d56Sopenharmony_ci        self.assertEqual(out.strip(), "OK")
6287db96d56Sopenharmony_ci
6297db96d56Sopenharmony_ci
6307db96d56Sopenharmony_ci    def test_no_pip_by_default(self):
6317db96d56Sopenharmony_ci        rmtree(self.env_dir)
6327db96d56Sopenharmony_ci        self.run_with_capture(venv.create, self.env_dir)
6337db96d56Sopenharmony_ci        self.assert_pip_not_installed()
6347db96d56Sopenharmony_ci
6357db96d56Sopenharmony_ci    def test_explicit_no_pip(self):
6367db96d56Sopenharmony_ci        rmtree(self.env_dir)
6377db96d56Sopenharmony_ci        self.run_with_capture(venv.create, self.env_dir, with_pip=False)
6387db96d56Sopenharmony_ci        self.assert_pip_not_installed()
6397db96d56Sopenharmony_ci
6407db96d56Sopenharmony_ci    def test_devnull(self):
6417db96d56Sopenharmony_ci        # Fix for issue #20053 uses os.devnull to force a config file to
6427db96d56Sopenharmony_ci        # appear empty. However http://bugs.python.org/issue20541 means
6437db96d56Sopenharmony_ci        # that doesn't currently work properly on Windows. Once that is
6447db96d56Sopenharmony_ci        # fixed, the "win_location" part of test_with_pip should be restored
6457db96d56Sopenharmony_ci        with open(os.devnull, "rb") as f:
6467db96d56Sopenharmony_ci            self.assertEqual(f.read(), b"")
6477db96d56Sopenharmony_ci
6487db96d56Sopenharmony_ci        self.assertTrue(os.path.exists(os.devnull))
6497db96d56Sopenharmony_ci
6507db96d56Sopenharmony_ci    def do_test_with_pip(self, system_site_packages):
6517db96d56Sopenharmony_ci        rmtree(self.env_dir)
6527db96d56Sopenharmony_ci        with EnvironmentVarGuard() as envvars:
6537db96d56Sopenharmony_ci            # pip's cross-version compatibility may trigger deprecation
6547db96d56Sopenharmony_ci            # warnings in current versions of Python. Ensure related
6557db96d56Sopenharmony_ci            # environment settings don't cause venv to fail.
6567db96d56Sopenharmony_ci            envvars["PYTHONWARNINGS"] = "ignore"
6577db96d56Sopenharmony_ci            # ensurepip is different enough from a normal pip invocation
6587db96d56Sopenharmony_ci            # that we want to ensure it ignores the normal pip environment
6597db96d56Sopenharmony_ci            # variable settings. We set PIP_NO_INSTALL here specifically
6607db96d56Sopenharmony_ci            # to check that ensurepip (and hence venv) ignores it.
6617db96d56Sopenharmony_ci            # See http://bugs.python.org/issue19734
6627db96d56Sopenharmony_ci            envvars["PIP_NO_INSTALL"] = "1"
6637db96d56Sopenharmony_ci            # Also check that we ignore the pip configuration file
6647db96d56Sopenharmony_ci            # See http://bugs.python.org/issue20053
6657db96d56Sopenharmony_ci            with tempfile.TemporaryDirectory() as home_dir:
6667db96d56Sopenharmony_ci                envvars["HOME"] = home_dir
6677db96d56Sopenharmony_ci                bad_config = "[global]\nno-install=1"
6687db96d56Sopenharmony_ci                # Write to both config file names on all platforms to reduce
6697db96d56Sopenharmony_ci                # cross-platform variation in test code behaviour
6707db96d56Sopenharmony_ci                win_location = ("pip", "pip.ini")
6717db96d56Sopenharmony_ci                posix_location = (".pip", "pip.conf")
6727db96d56Sopenharmony_ci                # Skips win_location due to http://bugs.python.org/issue20541
6737db96d56Sopenharmony_ci                for dirname, fname in (posix_location,):
6747db96d56Sopenharmony_ci                    dirpath = os.path.join(home_dir, dirname)
6757db96d56Sopenharmony_ci                    os.mkdir(dirpath)
6767db96d56Sopenharmony_ci                    fpath = os.path.join(dirpath, fname)
6777db96d56Sopenharmony_ci                    with open(fpath, 'w') as f:
6787db96d56Sopenharmony_ci                        f.write(bad_config)
6797db96d56Sopenharmony_ci
6807db96d56Sopenharmony_ci                # Actually run the create command with all that unhelpful
6817db96d56Sopenharmony_ci                # config in place to ensure we ignore it
6827db96d56Sopenharmony_ci                with self.nicer_error():
6837db96d56Sopenharmony_ci                    self.run_with_capture(venv.create, self.env_dir,
6847db96d56Sopenharmony_ci                                          system_site_packages=system_site_packages,
6857db96d56Sopenharmony_ci                                          with_pip=True)
6867db96d56Sopenharmony_ci        # Ensure pip is available in the virtual environment
6877db96d56Sopenharmony_ci        envpy = os.path.join(os.path.realpath(self.env_dir), self.bindir, self.exe)
6887db96d56Sopenharmony_ci        # Ignore DeprecationWarning since pip code is not part of Python
6897db96d56Sopenharmony_ci        out, err = check_output([envpy, '-W', 'ignore::DeprecationWarning',
6907db96d56Sopenharmony_ci               '-W', 'ignore::ImportWarning', '-I',
6917db96d56Sopenharmony_ci               '-m', 'pip', '--version'])
6927db96d56Sopenharmony_ci        # We force everything to text, so unittest gives the detailed diff
6937db96d56Sopenharmony_ci        # if we get unexpected results
6947db96d56Sopenharmony_ci        err = err.decode("latin-1") # Force to text, prevent decoding errors
6957db96d56Sopenharmony_ci        self.assertEqual(err, "")
6967db96d56Sopenharmony_ci        out = out.decode("latin-1") # Force to text, prevent decoding errors
6977db96d56Sopenharmony_ci        expected_version = "pip {}".format(ensurepip.version())
6987db96d56Sopenharmony_ci        self.assertEqual(out[:len(expected_version)], expected_version)
6997db96d56Sopenharmony_ci        env_dir = os.fsencode(self.env_dir).decode("latin-1")
7007db96d56Sopenharmony_ci        self.assertIn(env_dir, out)
7017db96d56Sopenharmony_ci
7027db96d56Sopenharmony_ci        # http://bugs.python.org/issue19728
7037db96d56Sopenharmony_ci        # Check the private uninstall command provided for the Windows
7047db96d56Sopenharmony_ci        # installers works (at least in a virtual environment)
7057db96d56Sopenharmony_ci        with EnvironmentVarGuard() as envvars:
7067db96d56Sopenharmony_ci            with self.nicer_error():
7077db96d56Sopenharmony_ci                # It seems ensurepip._uninstall calls subprocesses which do not
7087db96d56Sopenharmony_ci                # inherit the interpreter settings.
7097db96d56Sopenharmony_ci                envvars["PYTHONWARNINGS"] = "ignore"
7107db96d56Sopenharmony_ci                out, err = check_output([envpy,
7117db96d56Sopenharmony_ci                    '-W', 'ignore::DeprecationWarning',
7127db96d56Sopenharmony_ci                    '-W', 'ignore::ImportWarning', '-I',
7137db96d56Sopenharmony_ci                    '-m', 'ensurepip._uninstall'])
7147db96d56Sopenharmony_ci        # We force everything to text, so unittest gives the detailed diff
7157db96d56Sopenharmony_ci        # if we get unexpected results
7167db96d56Sopenharmony_ci        err = err.decode("latin-1") # Force to text, prevent decoding errors
7177db96d56Sopenharmony_ci        # Ignore the warning:
7187db96d56Sopenharmony_ci        #   "The directory '$HOME/.cache/pip/http' or its parent directory
7197db96d56Sopenharmony_ci        #    is not owned by the current user and the cache has been disabled.
7207db96d56Sopenharmony_ci        #    Please check the permissions and owner of that directory. If
7217db96d56Sopenharmony_ci        #    executing pip with sudo, you may want sudo's -H flag."
7227db96d56Sopenharmony_ci        # where $HOME is replaced by the HOME environment variable.
7237db96d56Sopenharmony_ci        err = re.sub("^(WARNING: )?The directory .* or its parent directory "
7247db96d56Sopenharmony_ci                     "is not owned or is not writable by the current user.*$", "",
7257db96d56Sopenharmony_ci                     err, flags=re.MULTILINE)
7267db96d56Sopenharmony_ci        self.assertEqual(err.rstrip(), "")
7277db96d56Sopenharmony_ci        # Being fairly specific regarding the expected behaviour for the
7287db96d56Sopenharmony_ci        # initial bundling phase in Python 3.4. If the output changes in
7297db96d56Sopenharmony_ci        # future pip versions, this test can likely be relaxed further.
7307db96d56Sopenharmony_ci        out = out.decode("latin-1") # Force to text, prevent decoding errors
7317db96d56Sopenharmony_ci        self.assertIn("Successfully uninstalled pip", out)
7327db96d56Sopenharmony_ci        self.assertIn("Successfully uninstalled setuptools", out)
7337db96d56Sopenharmony_ci        # Check pip is now gone from the virtual environment. This only
7347db96d56Sopenharmony_ci        # applies in the system_site_packages=False case, because in the
7357db96d56Sopenharmony_ci        # other case, pip may still be available in the system site-packages
7367db96d56Sopenharmony_ci        if not system_site_packages:
7377db96d56Sopenharmony_ci            self.assert_pip_not_installed()
7387db96d56Sopenharmony_ci
7397db96d56Sopenharmony_ci    @contextlib.contextmanager
7407db96d56Sopenharmony_ci    def nicer_error(self):
7417db96d56Sopenharmony_ci        """
7427db96d56Sopenharmony_ci        Capture output from a failed subprocess for easier debugging.
7437db96d56Sopenharmony_ci
7447db96d56Sopenharmony_ci        The output this handler produces can be a little hard to read,
7457db96d56Sopenharmony_ci        but at least it has all the details.
7467db96d56Sopenharmony_ci        """
7477db96d56Sopenharmony_ci        try:
7487db96d56Sopenharmony_ci            yield
7497db96d56Sopenharmony_ci        except subprocess.CalledProcessError as exc:
7507db96d56Sopenharmony_ci            out = (exc.output or b'').decode(errors="replace")
7517db96d56Sopenharmony_ci            err = (exc.stderr or b'').decode(errors="replace")
7527db96d56Sopenharmony_ci            self.fail(
7537db96d56Sopenharmony_ci                f"{exc}\n\n"
7547db96d56Sopenharmony_ci                f"**Subprocess Output**\n{out}\n\n"
7557db96d56Sopenharmony_ci                f"**Subprocess Error**\n{err}"
7567db96d56Sopenharmony_ci            )
7577db96d56Sopenharmony_ci
7587db96d56Sopenharmony_ci    @requires_venv_with_pip()
7597db96d56Sopenharmony_ci    def test_with_pip(self):
7607db96d56Sopenharmony_ci        self.do_test_with_pip(False)
7617db96d56Sopenharmony_ci        self.do_test_with_pip(True)
7627db96d56Sopenharmony_ci
7637db96d56Sopenharmony_ci
7647db96d56Sopenharmony_ciif __name__ == "__main__":
7657db96d56Sopenharmony_ci    unittest.main()
766