diff options
-rw-r--r-- | Lib/pkgutil.py | 14 | ||||
-rw-r--r-- | Lib/test/test_pkgutil.py | 11 | ||||
-rw-r--r-- | Lib/test/test_pydoc.py | 95 |
3 files changed, 75 insertions, 45 deletions
diff --git a/Lib/pkgutil.py b/Lib/pkgutil.py index c561c13..bdea23e 100644 --- a/Lib/pkgutil.py +++ b/Lib/pkgutil.py @@ -191,8 +191,11 @@ class ImpImporter: yielded = {} import inspect - - filenames = os.listdir(self.path) + try: + filenames = os.listdir(self.path) + except OSError: + # ignore unreadable directories like import does + filenames = [] filenames.sort() # handle packages before same-named modules for fn in filenames: @@ -205,7 +208,12 @@ class ImpImporter: if not modname and os.path.isdir(path) and '.' not in fn: modname = fn - for fn in os.listdir(path): + try: + dircontents = os.listdir(path) + except OSError: + # ignore unreadable directories like import does + dircontents = [] + for fn in dircontents: subname = inspect.getmodulename(fn) if subname=='__init__': ispkg = True diff --git a/Lib/test/test_pkgutil.py b/Lib/test/test_pkgutil.py index f69af5a..f755e67 100644 --- a/Lib/test/test_pkgutil.py +++ b/Lib/test/test_pkgutil.py @@ -84,6 +84,17 @@ class PkgutilTests(unittest.TestCase): del sys.modules[pkg] + def test_unreadable_dir_on_syspath(self): + # issue7367 - walk_packages failed if unreadable dir on sys.path + package_name = "unreadable_package" + d = os.path.join(self.dirname, package_name) + # this does not appear to create an unreadable dir on Windows + # but the test should not fail anyway + os.mkdir(d, 0) + for t in pkgutil.walk_packages(path=[self.dirname]): + self.fail("unexpected package found") + os.rmdir(d) + class PkgutilPEP302Tests(unittest.TestCase): class MyTestLoader(object): diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py index 6d3923f..3e5c450 100644 --- a/Lib/test/test_pydoc.py +++ b/Lib/test/test_pydoc.py @@ -7,7 +7,6 @@ import pydoc import keyword import re import string -import subprocess import test.support import time import unittest @@ -15,11 +14,9 @@ import xml.etree import textwrap from io import StringIO from collections import namedtuple -from contextlib import contextmanager - from test.script_helper import assert_python_ok from test.support import ( - TESTFN, forget, rmtree, EnvironmentVarGuard, + TESTFN, rmtree, reap_children, reap_threads, captured_output, captured_stdout, unlink ) from test import pydoc_mod @@ -209,7 +206,8 @@ def run_pydoc(module_name, *args, **env): output of pydoc. """ args = args + (module_name,) - rc, out, err = assert_python_ok(pydoc.__file__, *args, **env) + # do not write bytecode files to avoid caching errors + rc, out, err = assert_python_ok('-B', pydoc.__file__, *args, **env) return out.strip() def get_pydoc_html(module): @@ -295,43 +293,6 @@ class PydocDocTest(unittest.TestCase): self.assertEqual(expected, result, "documentation for missing module found") - def test_badimport(self): - # This tests the fix for issue 5230, where if pydoc found the module - # but the module had an internal import error pydoc would report no doc - # found. - modname = 'testmod_xyzzy' - testpairs = ( - ('i_am_not_here', 'i_am_not_here'), - ('test.i_am_not_here_either', 'i_am_not_here_either'), - ('test.i_am_not_here.neither_am_i', 'i_am_not_here.neither_am_i'), - ('i_am_not_here.{}'.format(modname), - 'i_am_not_here.{}'.format(modname)), - ('test.{}'.format(modname), modname), - ) - - @contextmanager - def newdirinpath(dir): - os.mkdir(dir) - sys.path.insert(0, dir) - try: - yield - finally: - sys.path.pop(0) - rmtree(dir) - - with newdirinpath(TESTFN): - fullmodname = os.path.join(TESTFN, modname) - sourcefn = fullmodname + os.extsep + "py" - for importstring, expectedinmsg in testpairs: - with open(sourcefn, 'w') as f: - f.write("import {}\n".format(importstring)) - try: - result = run_pydoc(modname, PYTHONPATH=TESTFN).decode("ascii") - finally: - forget(modname) - expected = badimport_pattern % (modname, expectedinmsg) - self.assertEqual(expected, result) - def test_input_strip(self): missing_module = " test.i_am_not_here " result = str(run_pydoc(missing_module), 'ascii') @@ -409,6 +370,55 @@ class PydocDocTest(unittest.TestCase): self.assertEqual(synopsis, 'line 1: h\xe9') +class PydocImportTest(unittest.TestCase): + + def setUp(self): + self.test_dir = os.mkdir(TESTFN) + self.addCleanup(rmtree, TESTFN) + + def test_badimport(self): + # This tests the fix for issue 5230, where if pydoc found the module + # but the module had an internal import error pydoc would report no doc + # found. + modname = 'testmod_xyzzy' + testpairs = ( + ('i_am_not_here', 'i_am_not_here'), + ('test.i_am_not_here_either', 'i_am_not_here_either'), + ('test.i_am_not_here.neither_am_i', 'i_am_not_here.neither_am_i'), + ('i_am_not_here.{}'.format(modname), + 'i_am_not_here.{}'.format(modname)), + ('test.{}'.format(modname), modname), + ) + + sourcefn = os.path.join(TESTFN, modname) + os.extsep + "py" + for importstring, expectedinmsg in testpairs: + with open(sourcefn, 'w') as f: + f.write("import {}\n".format(importstring)) + result = run_pydoc(modname, PYTHONPATH=TESTFN).decode("ascii") + expected = badimport_pattern % (modname, expectedinmsg) + self.assertEqual(expected, result) + + def test_apropos_with_bad_package(self): + # Issue 7425 - pydoc -k failed when bad package on path + pkgdir = os.path.join(TESTFN, "syntaxerr") + os.mkdir(pkgdir) + badsyntax = os.path.join(pkgdir, "__init__") + os.extsep + "py" + with open(badsyntax, 'w') as f: + f.write("invalid python syntax = $1\n") + result = run_pydoc('nothing', '-k', PYTHONPATH=TESTFN) + self.assertEqual(b'', result) + + def test_apropos_with_unreadable_dir(self): + # Issue 7367 - pydoc -k failed when unreadable dir on path + self.unreadable_dir = os.path.join(TESTFN, "unreadable") + os.mkdir(self.unreadable_dir, 0) + self.addCleanup(os.rmdir, self.unreadable_dir) + # Note, on Windows the directory appears to be still + # readable so this is not really testing the issue there + result = run_pydoc('nothing', '-k', PYTHONPATH=TESTFN) + self.assertEqual(b'', result) + + class TestDescriptions(unittest.TestCase): def test_module(self): @@ -517,6 +527,7 @@ class TestHelper(unittest.TestCase): def test_main(): try: test.support.run_unittest(PydocDocTest, + PydocImportTest, TestDescriptions, PydocServerTest, PydocUrlHandlerTest, |