bpo-33185: Fix regression in pydoc CLI sys.path handling (GH-6419) · python/cpython@d7ffa58

@@ -11,6 +11,7 @@

1111

import re

1212

import stat

1313

import string

14+

import tempfile

1415

import test.support

1516

import time

1617

import types

@@ -1084,6 +1085,71 @@ def test_resolve_false(self):

10841085

self.assertIn('class Enum', helptext)

10851086108610871088+

class TestInternalUtilities(unittest.TestCase):

1089+1090+

def setUp(self):

1091+

tmpdir = tempfile.TemporaryDirectory()

1092+

self.argv0dir = tmpdir.name

1093+

self.argv0 = os.path.join(tmpdir.name, "nonexistent")

1094+

self.addCleanup(tmpdir.cleanup)

1095+

self.abs_curdir = abs_curdir = os.getcwd()

1096+

self.curdir_spellings = ["", os.curdir, abs_curdir]

1097+1098+

def _get_revised_path(self, given_path, argv0=None):

1099+

# Checking that pydoc.cli() actually calls pydoc._get_revised_path()

1100+

# is handled via code review (at least for now).

1101+

if argv0 is None:

1102+

argv0 = self.argv0

1103+

return pydoc._get_revised_path(given_path, argv0)

1104+1105+

def _get_starting_path(self):

1106+

# Get a copy of sys.path without the current directory

1107+

clean_path = sys.path.copy()

1108+

for spelling in self.curdir_spellings:

1109+

for __ in range(clean_path.count(spelling)):

1110+

clean_path.remove(spelling)

1111+

return clean_path

1112+1113+

def test_sys_path_adjustment_adds_missing_curdir(self):

1114+

clean_path = self._get_starting_path()

1115+

expected_path = [self.abs_curdir] + clean_path

1116+

self.assertEqual(self._get_revised_path(clean_path), expected_path)

1117+1118+

def test_sys_path_adjustment_removes_argv0_dir(self):

1119+

clean_path = self._get_starting_path()

1120+

expected_path = [self.abs_curdir] + clean_path

1121+

leading_argv0dir = [self.argv0dir] + clean_path

1122+

self.assertEqual(self._get_revised_path(leading_argv0dir), expected_path)

1123+

trailing_argv0dir = clean_path + [self.argv0dir]

1124+

self.assertEqual(self._get_revised_path(trailing_argv0dir), expected_path)

1125+1126+1127+

def test_sys_path_adjustment_protects_pydoc_dir(self):

1128+

def _get_revised_path(given_path):

1129+

return self._get_revised_path(given_path, argv0=pydoc.__file__)

1130+

clean_path = self._get_starting_path()

1131+

leading_argv0dir = [self.argv0dir] + clean_path

1132+

expected_path = [self.abs_curdir] + leading_argv0dir

1133+

self.assertEqual(_get_revised_path(leading_argv0dir), expected_path)

1134+

trailing_argv0dir = clean_path + [self.argv0dir]

1135+

expected_path = [self.abs_curdir] + trailing_argv0dir

1136+

self.assertEqual(_get_revised_path(trailing_argv0dir), expected_path)

1137+1138+

def test_sys_path_adjustment_when_curdir_already_included(self):

1139+

clean_path = self._get_starting_path()

1140+

for spelling in self.curdir_spellings:

1141+

with self.subTest(curdir_spelling=spelling):

1142+

# If curdir is already present, no alterations are made at all

1143+

leading_curdir = [spelling] + clean_path

1144+

self.assertIsNone(self._get_revised_path(leading_curdir))

1145+

trailing_curdir = clean_path + [spelling]

1146+

self.assertIsNone(self._get_revised_path(trailing_curdir))

1147+

leading_argv0dir = [self.argv0dir] + leading_curdir

1148+

self.assertIsNone(self._get_revised_path(leading_argv0dir))

1149+

trailing_argv0dir = trailing_curdir + [self.argv0dir]

1150+

self.assertIsNone(self._get_revised_path(trailing_argv0dir))

1151+1152+10871153

@reap_threads

10881154

def test_main():

10891155

try:

@@ -1094,6 +1160,7 @@ def test_main():

10941160

PydocUrlHandlerTest,

10951161

TestHelper,

10961162

PydocWithMetaClasses,

1163+

TestInternalUtilities,

10971164

)

10981165

finally:

10991166

reap_children()