• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"""Tests for 'site'.
2
3Tests assume the initial paths in sys.path once the interpreter has begun
4executing have not been removed.
5
6"""
7import unittest
8import test.support
9from test import support
10from test.support import os_helper
11from test.support import socket_helper
12from test.support import captured_stderr
13from test.support.os_helper import TESTFN, EnvironmentVarGuard, change_cwd
14import builtins
15import encodings
16import glob
17import io
18import os
19import re
20import shutil
21import subprocess
22import sys
23import sysconfig
24import tempfile
25import urllib.error
26import urllib.request
27from unittest import mock
28from copy import copy
29
30# These tests are not particularly useful if Python was invoked with -S.
31# If you add tests that are useful under -S, this skip should be moved
32# to the class level.
33if sys.flags.no_site:
34    raise unittest.SkipTest("Python was invoked with -S")
35
36import site
37
38
39HAS_USER_SITE = (site.USER_SITE is not None)
40OLD_SYS_PATH = None
41
42
43def setUpModule():
44    global OLD_SYS_PATH
45    OLD_SYS_PATH = sys.path[:]
46
47    if site.ENABLE_USER_SITE and not os.path.isdir(site.USER_SITE):
48        # need to add user site directory for tests
49        try:
50            os.makedirs(site.USER_SITE)
51            # modify sys.path: will be restored by tearDownModule()
52            site.addsitedir(site.USER_SITE)
53        except PermissionError as exc:
54            raise unittest.SkipTest('unable to create user site directory (%r): %s'
55                                    % (site.USER_SITE, exc))
56
57
58def tearDownModule():
59    sys.path[:] = OLD_SYS_PATH
60
61
62class HelperFunctionsTests(unittest.TestCase):
63    """Tests for helper functions.
64    """
65
66    def setUp(self):
67        """Save a copy of sys.path"""
68        self.sys_path = sys.path[:]
69        self.old_base = site.USER_BASE
70        self.old_site = site.USER_SITE
71        self.old_prefixes = site.PREFIXES
72        self.original_vars = sysconfig._CONFIG_VARS
73        self.old_vars = copy(sysconfig._CONFIG_VARS)
74
75    def tearDown(self):
76        """Restore sys.path"""
77        sys.path[:] = self.sys_path
78        site.USER_BASE = self.old_base
79        site.USER_SITE = self.old_site
80        site.PREFIXES = self.old_prefixes
81        sysconfig._CONFIG_VARS = self.original_vars
82        # _CONFIG_VARS is None before get_config_vars() is called
83        if sysconfig._CONFIG_VARS is not None:
84            sysconfig._CONFIG_VARS.clear()
85            sysconfig._CONFIG_VARS.update(self.old_vars)
86
87    def test_makepath(self):
88        # Test makepath() have an absolute path for its first return value
89        # and a case-normalized version of the absolute path for its
90        # second value.
91        path_parts = ("Beginning", "End")
92        original_dir = os.path.join(*path_parts)
93        abs_dir, norm_dir = site.makepath(*path_parts)
94        self.assertEqual(os.path.abspath(original_dir), abs_dir)
95        if original_dir == os.path.normcase(original_dir):
96            self.assertEqual(abs_dir, norm_dir)
97        else:
98            self.assertEqual(os.path.normcase(abs_dir), norm_dir)
99
100    def test_init_pathinfo(self):
101        dir_set = site._init_pathinfo()
102        for entry in [site.makepath(path)[1] for path in sys.path
103                        if path and os.path.exists(path)]:
104            self.assertIn(entry, dir_set,
105                          "%s from sys.path not found in set returned "
106                          "by _init_pathinfo(): %s" % (entry, dir_set))
107
108    def pth_file_tests(self, pth_file):
109        """Contain common code for testing results of reading a .pth file"""
110        self.assertIn(pth_file.imported, sys.modules,
111                      "%s not in sys.modules" % pth_file.imported)
112        self.assertIn(site.makepath(pth_file.good_dir_path)[0], sys.path)
113        self.assertFalse(os.path.exists(pth_file.bad_dir_path))
114
115    def test_addpackage(self):
116        # Make sure addpackage() imports if the line starts with 'import',
117        # adds directories to sys.path for any line in the file that is not a
118        # comment or import that is a valid directory name for where the .pth
119        # file resides; invalid directories are not added
120        pth_file = PthFile()
121        pth_file.cleanup(prep=True)  # to make sure that nothing is
122                                      # pre-existing that shouldn't be
123        try:
124            pth_file.create()
125            site.addpackage(pth_file.base_dir, pth_file.filename, set())
126            self.pth_file_tests(pth_file)
127        finally:
128            pth_file.cleanup()
129
130    def make_pth(self, contents, pth_dir='.', pth_name=TESTFN):
131        # Create a .pth file and return its (abspath, basename).
132        pth_dir = os.path.abspath(pth_dir)
133        pth_basename = pth_name + '.pth'
134        pth_fn = os.path.join(pth_dir, pth_basename)
135        with open(pth_fn, 'w', encoding='utf-8') as pth_file:
136            self.addCleanup(lambda: os.remove(pth_fn))
137            pth_file.write(contents)
138        return pth_dir, pth_basename
139
140    def test_addpackage_import_bad_syntax(self):
141        # Issue 10642
142        pth_dir, pth_fn = self.make_pth("import bad-syntax\n")
143        with captured_stderr() as err_out:
144            site.addpackage(pth_dir, pth_fn, set())
145        self.assertRegex(err_out.getvalue(), "line 1")
146        self.assertRegex(err_out.getvalue(),
147            re.escape(os.path.join(pth_dir, pth_fn)))
148        # XXX: the previous two should be independent checks so that the
149        # order doesn't matter.  The next three could be a single check
150        # but my regex foo isn't good enough to write it.
151        self.assertRegex(err_out.getvalue(), 'Traceback')
152        self.assertRegex(err_out.getvalue(), r'import bad-syntax')
153        self.assertRegex(err_out.getvalue(), 'SyntaxError')
154
155    def test_addpackage_import_bad_exec(self):
156        # Issue 10642
157        pth_dir, pth_fn = self.make_pth("randompath\nimport nosuchmodule\n")
158        with captured_stderr() as err_out:
159            site.addpackage(pth_dir, pth_fn, set())
160        self.assertRegex(err_out.getvalue(), "line 2")
161        self.assertRegex(err_out.getvalue(),
162            re.escape(os.path.join(pth_dir, pth_fn)))
163        # XXX: ditto previous XXX comment.
164        self.assertRegex(err_out.getvalue(), 'Traceback')
165        self.assertRegex(err_out.getvalue(), 'ModuleNotFoundError')
166
167    def test_addpackage_empty_lines(self):
168        # Issue 33689
169        pth_dir, pth_fn = self.make_pth("\n\n  \n\n")
170        known_paths = site.addpackage(pth_dir, pth_fn, set())
171        self.assertEqual(known_paths, set())
172
173    def test_addpackage_import_bad_pth_file(self):
174        # Issue 5258
175        pth_dir, pth_fn = self.make_pth("abc\x00def\n")
176        with captured_stderr() as err_out:
177            self.assertFalse(site.addpackage(pth_dir, pth_fn, set()))
178        self.maxDiff = None
179        self.assertEqual(err_out.getvalue(), "")
180        for path in sys.path:
181            if isinstance(path, str):
182                self.assertNotIn("abc\x00def", path)
183
184    def test_addsitedir(self):
185        # Same tests for test_addpackage since addsitedir() essentially just
186        # calls addpackage() for every .pth file in the directory
187        pth_file = PthFile()
188        pth_file.cleanup(prep=True) # Make sure that nothing is pre-existing
189                                    # that is tested for
190        try:
191            pth_file.create()
192            site.addsitedir(pth_file.base_dir, set())
193            self.pth_file_tests(pth_file)
194        finally:
195            pth_file.cleanup()
196
197    # This tests _getuserbase, hence the double underline
198    # to distinguish from a test for getuserbase
199    def test__getuserbase(self):
200        self.assertEqual(site._getuserbase(), sysconfig._getuserbase())
201
202    @unittest.skipUnless(HAS_USER_SITE, 'need user site')
203    def test_get_path(self):
204        if sys.platform == 'darwin' and sys._framework:
205            scheme = 'osx_framework_user'
206        else:
207            scheme = os.name + '_user'
208        self.assertEqual(site._get_path(site._getuserbase()),
209                         sysconfig.get_path('purelib', scheme))
210
211    @unittest.skipUnless(site.ENABLE_USER_SITE, "requires access to PEP 370 "
212                          "user-site (site.ENABLE_USER_SITE)")
213    def test_s_option(self):
214        # (ncoghlan) Change this to use script_helper...
215        usersite = site.USER_SITE
216        self.assertIn(usersite, sys.path)
217
218        env = os.environ.copy()
219        rc = subprocess.call([sys.executable, '-c',
220            'import sys; sys.exit(%r in sys.path)' % usersite],
221            env=env)
222        self.assertEqual(rc, 1)
223
224        env = os.environ.copy()
225        rc = subprocess.call([sys.executable, '-s', '-c',
226            'import sys; sys.exit(%r in sys.path)' % usersite],
227            env=env)
228        if usersite == site.getsitepackages()[0]:
229            self.assertEqual(rc, 1)
230        else:
231            self.assertEqual(rc, 0, "User site still added to path with -s")
232
233        env = os.environ.copy()
234        env["PYTHONNOUSERSITE"] = "1"
235        rc = subprocess.call([sys.executable, '-c',
236            'import sys; sys.exit(%r in sys.path)' % usersite],
237            env=env)
238        if usersite == site.getsitepackages()[0]:
239            self.assertEqual(rc, 1)
240        else:
241            self.assertEqual(rc, 0,
242                        "User site still added to path with PYTHONNOUSERSITE")
243
244        env = os.environ.copy()
245        env["PYTHONUSERBASE"] = "/tmp"
246        rc = subprocess.call([sys.executable, '-c',
247            'import sys, site; sys.exit(site.USER_BASE.startswith("/tmp"))'],
248            env=env)
249        self.assertEqual(rc, 1,
250                        "User base not set by PYTHONUSERBASE")
251
252    @unittest.skipUnless(HAS_USER_SITE, 'need user site')
253    def test_getuserbase(self):
254        site.USER_BASE = None
255        user_base = site.getuserbase()
256
257        # the call sets site.USER_BASE
258        self.assertEqual(site.USER_BASE, user_base)
259
260        # let's set PYTHONUSERBASE and see if it uses it
261        site.USER_BASE = None
262        import sysconfig
263        sysconfig._CONFIG_VARS = None
264
265        with EnvironmentVarGuard() as environ:
266            environ['PYTHONUSERBASE'] = 'xoxo'
267            self.assertTrue(site.getuserbase().startswith('xoxo'),
268                            site.getuserbase())
269
270    @unittest.skipUnless(HAS_USER_SITE, 'need user site')
271    def test_getusersitepackages(self):
272        site.USER_SITE = None
273        site.USER_BASE = None
274        user_site = site.getusersitepackages()
275
276        # the call sets USER_BASE *and* USER_SITE
277        self.assertEqual(site.USER_SITE, user_site)
278        self.assertTrue(user_site.startswith(site.USER_BASE), user_site)
279        self.assertEqual(site.USER_BASE, site.getuserbase())
280
281    def test_getsitepackages(self):
282        site.PREFIXES = ['xoxo']
283        dirs = site.getsitepackages()
284        if os.sep == '/':
285            # OS X, Linux, FreeBSD, etc
286            if sys.platlibdir != "lib":
287                self.assertEqual(len(dirs), 2)
288                wanted = os.path.join('xoxo', sys.platlibdir,
289                                      'python%d.%d' % sys.version_info[:2],
290                                      'site-packages')
291                self.assertEqual(dirs[0], wanted)
292            else:
293                self.assertEqual(len(dirs), 1)
294            wanted = os.path.join('xoxo', 'lib',
295                                  'python%d.%d' % sys.version_info[:2],
296                                  'site-packages')
297            self.assertEqual(dirs[-1], wanted)
298        else:
299            # other platforms
300            self.assertEqual(len(dirs), 2)
301            self.assertEqual(dirs[0], 'xoxo')
302            wanted = os.path.join('xoxo', 'lib', 'site-packages')
303            self.assertEqual(dirs[1], wanted)
304
305    @unittest.skipUnless(HAS_USER_SITE, 'need user site')
306    def test_no_home_directory(self):
307        # bpo-10496: getuserbase() and getusersitepackages() must not fail if
308        # the current user has no home directory (if expanduser() returns the
309        # path unchanged).
310        site.USER_SITE = None
311        site.USER_BASE = None
312
313        with EnvironmentVarGuard() as environ, \
314             mock.patch('os.path.expanduser', lambda path: path):
315
316            del environ['PYTHONUSERBASE']
317            del environ['APPDATA']
318
319            user_base = site.getuserbase()
320            self.assertTrue(user_base.startswith('~' + os.sep),
321                            user_base)
322
323            user_site = site.getusersitepackages()
324            self.assertTrue(user_site.startswith(user_base), user_site)
325
326        with mock.patch('os.path.isdir', return_value=False) as mock_isdir, \
327             mock.patch.object(site, 'addsitedir') as mock_addsitedir, \
328             support.swap_attr(site, 'ENABLE_USER_SITE', True):
329
330            # addusersitepackages() must not add user_site to sys.path
331            # if it is not an existing directory
332            known_paths = set()
333            site.addusersitepackages(known_paths)
334
335            mock_isdir.assert_called_once_with(user_site)
336            mock_addsitedir.assert_not_called()
337            self.assertFalse(known_paths)
338
339    def test_trace(self):
340        message = "bla-bla-bla"
341        for verbose, out in (True, message + "\n"), (False, ""):
342            with mock.patch('sys.flags', mock.Mock(verbose=verbose)), \
343                    mock.patch('sys.stderr', io.StringIO()):
344                site._trace(message)
345                self.assertEqual(sys.stderr.getvalue(), out)
346
347
348class PthFile(object):
349    """Helper class for handling testing of .pth files"""
350
351    def __init__(self, filename_base=TESTFN, imported="time",
352                    good_dirname="__testdir__", bad_dirname="__bad"):
353        """Initialize instance variables"""
354        self.filename = filename_base + ".pth"
355        self.base_dir = os.path.abspath('')
356        self.file_path = os.path.join(self.base_dir, self.filename)
357        self.imported = imported
358        self.good_dirname = good_dirname
359        self.bad_dirname = bad_dirname
360        self.good_dir_path = os.path.join(self.base_dir, self.good_dirname)
361        self.bad_dir_path = os.path.join(self.base_dir, self.bad_dirname)
362
363    def create(self):
364        """Create a .pth file with a comment, blank lines, an ``import
365        <self.imported>``, a line with self.good_dirname, and a line with
366        self.bad_dirname.
367
368        Creation of the directory for self.good_dir_path (based off of
369        self.good_dirname) is also performed.
370
371        Make sure to call self.cleanup() to undo anything done by this method.
372
373        """
374        FILE = open(self.file_path, 'w')
375        try:
376            print("#import @bad module name", file=FILE)
377            print("\n", file=FILE)
378            print("import %s" % self.imported, file=FILE)
379            print(self.good_dirname, file=FILE)
380            print(self.bad_dirname, file=FILE)
381        finally:
382            FILE.close()
383        os.mkdir(self.good_dir_path)
384
385    def cleanup(self, prep=False):
386        """Make sure that the .pth file is deleted, self.imported is not in
387        sys.modules, and that both self.good_dirname and self.bad_dirname are
388        not existing directories."""
389        if os.path.exists(self.file_path):
390            os.remove(self.file_path)
391        if prep:
392            self.imported_module = sys.modules.get(self.imported)
393            if self.imported_module:
394                del sys.modules[self.imported]
395        else:
396            if self.imported_module:
397                sys.modules[self.imported] = self.imported_module
398        if os.path.exists(self.good_dir_path):
399            os.rmdir(self.good_dir_path)
400        if os.path.exists(self.bad_dir_path):
401            os.rmdir(self.bad_dir_path)
402
403class ImportSideEffectTests(unittest.TestCase):
404    """Test side-effects from importing 'site'."""
405
406    def setUp(self):
407        """Make a copy of sys.path"""
408        self.sys_path = sys.path[:]
409
410    def tearDown(self):
411        """Restore sys.path"""
412        sys.path[:] = self.sys_path
413
414    def test_abs_paths_cached_None(self):
415        """Test for __cached__ is None.
416
417        Regarding to PEP 3147, __cached__ can be None.
418
419        See also: https://bugs.python.org/issue30167
420        """
421        sys.modules['test'].__cached__ = None
422        site.abs_paths()
423        self.assertIsNone(sys.modules['test'].__cached__)
424
425    def test_no_duplicate_paths(self):
426        # No duplicate paths should exist in sys.path
427        # Handled by removeduppaths()
428        site.removeduppaths()
429        seen_paths = set()
430        for path in sys.path:
431            self.assertNotIn(path, seen_paths)
432            seen_paths.add(path)
433
434    @unittest.skip('test not implemented')
435    def test_add_build_dir(self):
436        # Test that the build directory's Modules directory is used when it
437        # should be.
438        # XXX: implement
439        pass
440
441    def test_setting_quit(self):
442        # 'quit' and 'exit' should be injected into builtins
443        self.assertTrue(hasattr(builtins, "quit"))
444        self.assertTrue(hasattr(builtins, "exit"))
445
446    def test_setting_copyright(self):
447        # 'copyright', 'credits', and 'license' should be in builtins
448        self.assertTrue(hasattr(builtins, "copyright"))
449        self.assertTrue(hasattr(builtins, "credits"))
450        self.assertTrue(hasattr(builtins, "license"))
451
452    def test_setting_help(self):
453        # 'help' should be set in builtins
454        self.assertTrue(hasattr(builtins, "help"))
455
456    def test_aliasing_mbcs(self):
457        if sys.platform == "win32":
458            import locale
459            if locale.getdefaultlocale()[1].startswith('cp'):
460                for value in encodings.aliases.aliases.values():
461                    if value == "mbcs":
462                        break
463                else:
464                    self.fail("did not alias mbcs")
465
466    def test_sitecustomize_executed(self):
467        # If sitecustomize is available, it should have been imported.
468        if "sitecustomize" not in sys.modules:
469            try:
470                import sitecustomize
471            except ImportError:
472                pass
473            else:
474                self.fail("sitecustomize not imported automatically")
475
476    @test.support.requires_resource('network')
477    @test.support.system_must_validate_cert
478    @unittest.skipUnless(hasattr(urllib.request, "HTTPSHandler"),
479                         'need SSL support to download license')
480    def test_license_exists_at_url(self):
481        # This test is a bit fragile since it depends on the format of the
482        # string displayed by license in the absence of a LICENSE file.
483        url = license._Printer__data.split()[1]
484        req = urllib.request.Request(url, method='HEAD')
485        # Reset global urllib.request._opener
486        self.addCleanup(urllib.request.urlcleanup)
487        try:
488            with socket_helper.transient_internet(url):
489                with urllib.request.urlopen(req) as data:
490                    code = data.getcode()
491        except urllib.error.HTTPError as e:
492            code = e.code
493        self.assertEqual(code, 200, msg="Can't find " + url)
494
495
496class StartupImportTests(unittest.TestCase):
497
498    def test_startup_imports(self):
499        # Get sys.path in isolated mode (python3 -I)
500        popen = subprocess.Popen([sys.executable, '-I', '-c',
501                                  'import sys; print(repr(sys.path))'],
502                                 stdout=subprocess.PIPE,
503                                 encoding='utf-8')
504        stdout = popen.communicate()[0]
505        self.assertEqual(popen.returncode, 0, repr(stdout))
506        isolated_paths = eval(stdout)
507
508        # bpo-27807: Even with -I, the site module executes all .pth files
509        # found in sys.path (see site.addpackage()). Skip the test if at least
510        # one .pth file is found.
511        for path in isolated_paths:
512            pth_files = glob.glob(os.path.join(glob.escape(path), "*.pth"))
513            if pth_files:
514                self.skipTest(f"found {len(pth_files)} .pth files in: {path}")
515
516        # This tests checks which modules are loaded by Python when it
517        # initially starts upon startup.
518        popen = subprocess.Popen([sys.executable, '-I', '-v', '-c',
519                                  'import sys; print(set(sys.modules))'],
520                                 stdout=subprocess.PIPE,
521                                 stderr=subprocess.PIPE,
522                                 encoding='utf-8')
523        stdout, stderr = popen.communicate()
524        self.assertEqual(popen.returncode, 0, (stdout, stderr))
525        modules = eval(stdout)
526
527        self.assertIn('site', modules)
528
529        # http://bugs.python.org/issue19205
530        re_mods = {'re', '_sre', 'sre_compile', 'sre_constants', 'sre_parse'}
531        self.assertFalse(modules.intersection(re_mods), stderr)
532
533        # http://bugs.python.org/issue9548
534        self.assertNotIn('locale', modules, stderr)
535
536        # http://bugs.python.org/issue19209
537        self.assertNotIn('copyreg', modules, stderr)
538
539        # http://bugs.python.org/issue19218
540        collection_mods = {'_collections', 'collections', 'functools',
541                           'heapq', 'itertools', 'keyword', 'operator',
542                           'reprlib', 'types', 'weakref'
543                          }.difference(sys.builtin_module_names)
544        self.assertFalse(modules.intersection(collection_mods), stderr)
545
546    def test_startup_interactivehook(self):
547        r = subprocess.Popen([sys.executable, '-c',
548            'import sys; sys.exit(hasattr(sys, "__interactivehook__"))']).wait()
549        self.assertTrue(r, "'__interactivehook__' not added by site")
550
551    def test_startup_interactivehook_isolated(self):
552        # issue28192 readline is not automatically enabled in isolated mode
553        r = subprocess.Popen([sys.executable, '-I', '-c',
554            'import sys; sys.exit(hasattr(sys, "__interactivehook__"))']).wait()
555        self.assertFalse(r, "'__interactivehook__' added in isolated mode")
556
557    def test_startup_interactivehook_isolated_explicit(self):
558        # issue28192 readline can be explicitly enabled in isolated mode
559        r = subprocess.Popen([sys.executable, '-I', '-c',
560            'import site, sys; site.enablerlcompleter(); sys.exit(hasattr(sys, "__interactivehook__"))']).wait()
561        self.assertTrue(r, "'__interactivehook__' not added by enablerlcompleter()")
562
563@unittest.skipUnless(sys.platform == 'win32', "only supported on Windows")
564class _pthFileTests(unittest.TestCase):
565
566    def _create_underpth_exe(self, lines, exe_pth=True):
567        import _winapi
568        temp_dir = tempfile.mkdtemp()
569        self.addCleanup(os_helper.rmtree, temp_dir)
570        exe_file = os.path.join(temp_dir, os.path.split(sys.executable)[1])
571        dll_src_file = _winapi.GetModuleFileName(sys.dllhandle)
572        dll_file = os.path.join(temp_dir, os.path.split(dll_src_file)[1])
573        shutil.copy(sys.executable, exe_file)
574        shutil.copy(dll_src_file, dll_file)
575        if exe_pth:
576            _pth_file = os.path.splitext(exe_file)[0] + '._pth'
577        else:
578            _pth_file = os.path.splitext(dll_file)[0] + '._pth'
579        with open(_pth_file, 'w') as f:
580            for line in lines:
581                print(line, file=f)
582        return exe_file
583
584    def _calc_sys_path_for_underpth_nosite(self, sys_prefix, lines):
585        sys_path = []
586        for line in lines:
587            if not line or line[0] == '#':
588                continue
589            abs_path = os.path.abspath(os.path.join(sys_prefix, line))
590            sys_path.append(abs_path)
591        return sys_path
592
593    def test_underpth_nosite_file(self):
594        libpath = os.path.dirname(os.path.dirname(encodings.__file__))
595        exe_prefix = os.path.dirname(sys.executable)
596        pth_lines = [
597            'fake-path-name',
598            *[libpath for _ in range(200)],
599            '',
600            '# comment',
601        ]
602        exe_file = self._create_underpth_exe(pth_lines)
603        sys_path = self._calc_sys_path_for_underpth_nosite(
604            os.path.dirname(exe_file),
605            pth_lines)
606
607        env = os.environ.copy()
608        env['PYTHONPATH'] = 'from-env'
609        env['PATH'] = '{};{}'.format(exe_prefix, os.getenv('PATH'))
610        output = subprocess.check_output([exe_file, '-c',
611            'import sys; print("\\n".join(sys.path) if sys.flags.no_site else "")'
612        ], env=env, encoding='ansi')
613        actual_sys_path = output.rstrip().split('\n')
614        self.assertTrue(actual_sys_path, "sys.flags.no_site was False")
615        self.assertEqual(
616            actual_sys_path,
617            sys_path,
618            "sys.path is incorrect"
619        )
620
621    def test_underpth_file(self):
622        libpath = os.path.dirname(os.path.dirname(encodings.__file__))
623        exe_prefix = os.path.dirname(sys.executable)
624        exe_file = self._create_underpth_exe([
625            'fake-path-name',
626            *[libpath for _ in range(200)],
627            '',
628            '# comment',
629            'import site'
630        ])
631        sys_prefix = os.path.dirname(exe_file)
632        env = os.environ.copy()
633        env['PYTHONPATH'] = 'from-env'
634        env['PATH'] = '{};{}'.format(exe_prefix, os.getenv('PATH'))
635        rc = subprocess.call([exe_file, '-c',
636            'import sys; sys.exit(not sys.flags.no_site and '
637            '%r in sys.path and %r in sys.path and %r not in sys.path and '
638            'all("\\r" not in p and "\\n" not in p for p in sys.path))' % (
639                os.path.join(sys_prefix, 'fake-path-name'),
640                libpath,
641                os.path.join(sys_prefix, 'from-env'),
642            )], env=env)
643        self.assertTrue(rc, "sys.path is incorrect")
644
645
646    def test_underpth_dll_file(self):
647        libpath = os.path.dirname(os.path.dirname(encodings.__file__))
648        exe_prefix = os.path.dirname(sys.executable)
649        exe_file = self._create_underpth_exe([
650            'fake-path-name',
651            *[libpath for _ in range(200)],
652            '',
653            '# comment',
654            'import site'
655        ], exe_pth=False)
656        sys_prefix = os.path.dirname(exe_file)
657        env = os.environ.copy()
658        env['PYTHONPATH'] = 'from-env'
659        env['PATH'] = '{};{}'.format(exe_prefix, os.getenv('PATH'))
660        rc = subprocess.call([exe_file, '-c',
661            'import sys; sys.exit(not sys.flags.no_site and '
662            '%r in sys.path and %r in sys.path and %r not in sys.path and '
663            'all("\\r" not in p and "\\n" not in p for p in sys.path))' % (
664                os.path.join(sys_prefix, 'fake-path-name'),
665                libpath,
666                os.path.join(sys_prefix, 'from-env'),
667            )], env=env)
668        self.assertTrue(rc, "sys.path is incorrect")
669
670
671if __name__ == "__main__":
672    unittest.main()
673