]> granicus.if.org Git - python/commitdiff
Fix issue 5230 by having pydoc's safeimport check to see if the import
authorR. David Murray <rdmurray@bitdance.com>
Tue, 23 Jun 2009 18:02:46 +0000 (18:02 +0000)
committerR. David Murray <rdmurray@bitdance.com>
Tue, 23 Jun 2009 18:02:46 +0000 (18:02 +0000)
error was thrown from itself in order to decide if the module can't be
found.  Thanks to Lucas Prado Melo for collaborating on the fix and tests.

Lib/pydoc.py
Lib/test/test_pydoc.py
Misc/ACKS
Misc/NEWS

index 76a2b6462124181c4e3f40c60858e8168072161d..57071a15066c2a17d797e9122a22def8936806fe 100755 (executable)
@@ -55,6 +55,7 @@ Richard Chamberlain, for the first implementation of textdoc.
 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 @@ def safeimport(path, forceload=0, cache={}):
         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 7990d3a492d9e7327e5bc5a9aaaa642766c65e21..c1c19f608309d0c4d886dcd509a64363352eed0f 100644 (file)
@@ -1,5 +1,6 @@
 import sys
 import os
+import os.path
 import difflib
 import subprocess
 import re
@@ -7,6 +8,8 @@ import pydoc
 import inspect
 import unittest
 import test.test_support
+from contextlib import contextmanager
+from test.test_support import TESTFN, forget, rmtree, EnvironmentVarGuard
 
 from test import pydoc_mod
 
@@ -166,6 +169,9 @@ war</tt></dd></dl>
 # 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 - <type 'exceptions.ImportError'>: No module named %s"
+
 def run_pydoc(module_name, *args):
     """
     Runs pydoc on the specified module. Returns the stripped
@@ -237,6 +243,42 @@ 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)
+            yield
+            sys.path.pop(0)
+            rmtree(dir)
+
+        with newdirinpath(TESTFN), EnvironmentVarGuard() as env:
+            env['PYTHONPATH'] = TESTFN
+            fullmodname = os.path.join(TESTFN, modname)
+            sourcefn = fullmodname + os.extsep + "py"
+            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)
+
     def test_input_strip(self):
         missing_module = " test.i_am_not_here "
         result = run_pydoc(missing_module)
index 82cd4a3c2550b4eb9509eef927c245897ffa8506..5cc07e57192b3edb39c18ff789dc5599e7c44100 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -479,6 +479,7 @@ Andrew McNamara
 Craig McPheeters
 Lambert Meertens
 Bill van Melle
+Lucas Prado Melo
 Luke Mewburn
 Mike Meyer
 Steven Miale
index 2985c3aa70e18014c38bcc9035e52bc541cdd70c..a4e92f4509042d5eb9dbf4011894eae86fb0c03e 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -327,6 +327,10 @@ Core and Builtins
 Library
 -------
 
+- Issue #5230: pydoc would report no documentation found if a module generated
+  a 'not found' import error when loaded; it now reports the import errors.
+  Thanks to Lucas Prado Melo for initial fix and collaboration on the tests.
+
 - Issue #6314: logging.basicConfig() performs extra checks on the "level"
   argument.