Index: Lib/pydoc.py =================================================================== --- Lib/pydoc.py (revision 73511) +++ Lib/pydoc.py (working copy) @@ -55,6 +55,7 @@ import sys, imp, os, re, types, inspect, __builtin__, pkgutil from repr import Repr from string import expandtabs, find, join, lower, split, strip, rfind, rstrip +from traceback import extract_tb try: from collections import deque except ImportError: @@ -299,9 +300,9 @@ elif exc is SyntaxError: # A SyntaxError occurred before we could execute the module. raise ErrorDuringImport(value.filename, info) - elif exc is ImportError and \ - split(lower(str(value)))[:2] == ['no', 'module']: - # The module was not found. + elif exc is ImportError and extract_tb(tb)[-1][2]=='safeimport': + # The import error occurred directly in this function, + # which means there is no such module in the path. return None else: # Some other error occurred during the importing process. Index: Lib/test/test_pydoc.py =================================================================== --- Lib/test/test_pydoc.py (revision 73511) +++ Lib/test/test_pydoc.py (working copy) @@ -1,5 +1,6 @@ import sys import os +import os.path import difflib import subprocess import re @@ -7,6 +8,7 @@ import inspect import unittest import test.test_support +from test.test_support import TESTFN, forget, rmtree, EnvironmentVarGuard from test import pydoc_mod @@ -166,6 +168,9 @@ # output pattern for missing module missing_pattern = "no Python documentation found for '%s'" +# output pattern for module with bad imports +badimport_pattern = "problem in %s - : No module named %s" + def run_pydoc(module_name, *args): """ Runs pydoc on the specified module. Returns the stripped @@ -237,6 +242,40 @@ 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. However, there is one (rare) case we weren't able to fix, + # which will still give the misleading no doc found message. + 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)), + #XXX: this case fails and I can't figure out how to fix it. + ('test.{}'.format(modname), modname), + ) + os.mkdir(TESTFN) + sys.path.insert(0, TESTFN) + with EnvironmentVarGuard() as env: + env['PYTHONPATH'] = TESTFN + fullmodname = os.path.join(TESTFN, modname) + sourcefn = fullmodname + os.extsep + "py" + try: + for importstring, expectedinmsg in testpairs: + f = open(sourcefn, 'w') + f.write("import {}\n".format(importstring)) + f.close() + try: + result = run_pydoc(modname) + finally: + forget(modname) + expected = badimport_pattern % (modname, expectedinmsg) + self.assertEqual(expected, result) + finally: + rmtree(TESTFN) + def test_input_strip(self): missing_module = " test.i_am_not_here " result = run_pydoc(missing_module)