[Python-checkins] CVS: python/dist/src/Lib pydoc.py,1.17,1.18

Ka-Ping Yee ping@users.sourceforge.net
Fri, 23 Mar 2001 05:17:52 -0800


Update of /cvsroot/python/python/dist/src/Lib
In directory usw-pr-cvs1:/tmp/cvs-serv26388

Modified Files:
	pydoc.py 
Log Message:
Show inherited methods, with hyperlinks to the base class they came from.
Font adjustment to improve viewing in Windows (the default monospaced font,
    Courier New, seems to have no reasonable size in IE!)
Improve error handling.  Try very hard to distinguish between failure to
    find a module and failure during the module importing process.
Improve reloading behaviour.  (Still needs some work.)
Add '.' to sys.path when running as a script at the command-line.
Don't automatically assume '-g' based on the platform.  We'll just have
    the batch file supply -g.



Index: pydoc.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/pydoc.py,v
retrieving revision 1.17
retrieving revision 1.18
diff -C2 -r1.17 -r1.18
*** pydoc.py	2001/03/23 00:12:53	1.17
--- pydoc.py	2001/03/23 13:17:50	1.18
***************
*** 42,46 ****
  import sys, imp, os, stat, re, types, inspect
  from repr import Repr
! from string import expandtabs, find, join, lower, split, strip, rstrip
  
  # --------------------------------------------------------- common routines
--- 42,46 ----
  import sys, imp, os, stat, re, types, inspect
  from repr import Repr
! from string import expandtabs, find, join, lower, split, strip, rfind, rstrip
  
  # --------------------------------------------------------- common routines
***************
*** 85,92 ****
  def getdoc(object):
      """Get the doc string or comments for an object."""
!     result = inspect.getdoc(object)
!     if not result:
!         try: result = inspect.getcomments(object)
!         except: pass
      return result and re.sub('^ *\n', '', rstrip(result)) or ''
  
--- 85,89 ----
  def getdoc(object):
      """Get the doc string or comments for an object."""
!     result = inspect.getdoc(object) or inspect.getcomments(object)
      return result and re.sub('^ *\n', '', rstrip(result)) or ''
  
***************
*** 138,154 ****
              return filename[:-length]
  
! class DocImportError(Exception):
!     """Class for errors while trying to import something to document it."""
!     def __init__(self, filename, (type, value, tb)):
          self.filename = filename
!         self.type = type
          self.value = value
          self.tb = tb
  
      def __str__(self):
!         t = self.type
!         if type(t) is types.ClassType:
!             t = t.__name__
!         return 'problem in %s - %s: %s' % (self.filename, t, self.value)
  
  def importfile(path):
--- 135,161 ----
              return filename[:-length]
  
! def allmethods(cl):
!     methods = {}
!     for key, value in inspect.getmembers(cl, inspect.ismethod):
!         methods[key] = 1
!     for base in cl.__bases__:
!         methods.update(allmethods(base)) # all your base are belong to us
!     for key in methods.keys():
!         methods[key] = getattr(cl, key)
!     return methods
! 
! class ErrorDuringImport(Exception):
!     """Errors that occurred while trying to import something to document it."""
!     def __init__(self, filename, (exc, value, tb)):
          self.filename = filename
!         self.exc = exc
          self.value = value
          self.tb = tb
  
      def __str__(self):
!         exc = self.exc
!         if type(exc) is types.ClassType:
!             exc = exc.__name__
!         return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
  
  def importfile(path):
***************
*** 167,171 ****
          module = imp.load_module(name, file, path, (ext, 'r', kind))
      except:
!         raise DocImportError(path, sys.exc_info())
      file.close()
      return module
--- 174,178 ----
          module = imp.load_module(name, file, path, (ext, 'r', kind))
      except:
!         raise ErrorDuringImport(path, sys.exc_info())
      file.close()
      return module
***************
*** 251,255 ****
          return '''
  <!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">
! <html><title>Python: %s</title><body bgcolor="#f0f0f8">
  %s
  </body></html>''' % (title, contents)
--- 258,264 ----
          return '''
  <!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">
! <html><head><title>Python: %s</title>
! <style>TT { font-family: lucida console, lucida typewriter, courier }</style>
! </head><body bgcolor="#f0f0f8">
  %s
  </body></html>''' % (title, contents)
***************
*** 280,288 ****
              result = result + '''
  <tr bgcolor="%s"><td>%s</td>
! <td colspan=2>%s</td></tr>
!     ''' % (bgcol, marginalia, prelude)
          result = result + '''
! <tr><td bgcolor="%s">%s</td><td>%s</td>
!     ''' % (bgcol, marginalia, gap)
  
          return result + '<td width="100%%">%s</td></tr></table>' % contents
--- 289,295 ----
              result = result + '''
  <tr bgcolor="%s"><td>%s</td>
! <td colspan=2>%s</td></tr>''' % (bgcol, marginalia, prelude)
          result = result + '''
! <tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
  
          return result + '<td width="100%%">%s</td></tr></table>' % contents
***************
*** 307,311 ****
              for i in range(rows*col, rows*col+rows):
                  if i < len(list):
!                     result = result + format(list[i]) + '<br>'
              result = result + '</td>'
          return '<table width="100%%"><tr>%s</tr></table>' % result
--- 314,318 ----
              for i in range(rows*col, rows*col+rows):
                  if i < len(list):
!                     result = result + format(list[i]) + '<br>\n'
              result = result + '</td>'
          return '<table width="100%%"><tr>%s</tr></table>' % result
***************
*** 355,360 ****
          results = []
          here = 0
!         pattern = re.compile(r'\b(((http|ftp)://\S+[\w/])|'
!                                 r'(RFC[- ]?(\d+))|'
                                  r'(self\.)?(\w+))\b')
          while 1:
--- 362,367 ----
          results = []
          here = 0
!         pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
!                                 r'RFC[- ]?(\d+)|'
                                  r'(self\.)?(\w+))\b')
          while 1:
***************
*** 364,380 ****
              results.append(escape(text[here:start]))
  
!             all, url, scheme, rfc, rfcnum, selfdot, name = match.groups()
!             if url:
!                 results.append('<a href="%s">%s</a>' % (url, escape(url)))
              elif rfc:
!                 url = 'http://www.rfc-editor.org/rfc/rfc%s.txt' % rfcnum
!                 results.append('<a href="%s">%s</a>' % (url, escape(rfc)))
              else:
!                 if text[end:end+1] == '(':
!                     results.append(self.namelink(name, methods, funcs, classes))
!                 elif selfdot:
!                     results.append('self.<strong>%s</strong>' % name)
!                 else:
!                     results.append(self.namelink(name, classes))
              here = end
          results.append(escape(text[here:]))
--- 371,386 ----
              results.append(escape(text[here:start]))
  
!             all, scheme, rfc, selfdot, name = match.groups()
!             if scheme:
!                 results.append('<a href="%s">%s</a>' % (all, escape(all)))
              elif rfc:
!                 url = 'http://www.rfc-editor.org/rfc/rfc%s.txt' % rfc
!                 results.append('<a href="%s">%s</a>' % (url, escape(all)))
!             elif text[end:end+1] == '(':
!                 results.append(self.namelink(name, methods, funcs, classes))
!             elif selfdot:
!                 results.append('self.<strong>%s</strong>' % name)
              else:
!                 results.append(self.namelink(name, classes))
              here = end
          results.append(escape(text[here:]))
***************
*** 529,538 ****
  
          methods, mdict = [], {}
!         for key, value in inspect.getmembers(object, inspect.ismethod):
              methods.append((key, value))
              mdict[key] = mdict[value] = '#' + name + '-' + key
          for key, value in methods:
              contents = contents + self.document(
!                 value, key, funcs, classes, mdict, name)
  
          if name == realname:
--- 535,545 ----
  
          methods, mdict = [], {}
!         for key, value in allmethods(object).items():
              methods.append((key, value))
              mdict[key] = mdict[value] = '#' + name + '-' + key
+         methods.sort()
          for key, value in methods:
              contents = contents + self.document(
!                 value, key, funcs, classes, mdict, object)
  
          if name == realname:
***************
*** 542,546 ****
              title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
                  name, name, realname)
- 
          if bases:
              parents = []
--- 549,552 ----
***************
*** 551,555 ****
          doc = self.markup(
              getdoc(object), self.preformat, funcs, classes, mdict)
!         if doc: doc = self.small('<tt>%s</tt>' % doc)
          return self.section(title, '#000000', '#ffc8d8', contents, 10, doc)
  
--- 557,561 ----
          doc = self.markup(
              getdoc(object), self.preformat, funcs, classes, mdict)
!         doc = self.small('<tt>%s<br>&nbsp;</tt>' % doc)
          return self.section(title, '#000000', '#ffc8d8', contents, 10, doc)
  
***************
*** 559,574 ****
  
      def docroutine(self, object, name=None,
!                    funcs={}, classes={}, methods={}, clname=''):
          """Produce HTML documentation for a function or method object."""
          realname = object.__name__
          name = name or realname
!         anchor = clname + '-' + realname
          note = ''
          if inspect.ismethod(object):
!             if not clname:
!                 note = self.small(self.grey(
!                     object.im_self and
                          'method of ' + self.repr(object.im_self) or
!                         ' unbound %s method' % object.im_class.__name__))
              object = object.im_func
  
--- 565,590 ----
  
      def docroutine(self, object, name=None,
!                    funcs={}, classes={}, methods={}, cl=None):
          """Produce HTML documentation for a function or method object."""
          realname = object.__name__
          name = name or realname
!         anchor = (cl and cl.__name__ or '') + '-' + name
          note = ''
+         skipdocs = 0
          if inspect.ismethod(object):
!             if cl:
!                 if not cl.__dict__.has_key(name):
!                     base = object.im_class
!                     url = '#%s-%s' % (base.__name__, name)
!                     basename = base.__name__
!                     if base.__module__ != cl.__module__:
!                         url = base.__module__ + '.html' + url
!                         basename = base.__module__ + '.' + basename
!                     note = ' from <a href="%s">%s</a>' % (url, basename)
!                     skipdocs = 1
!             else:
!                 note = (object.im_self and
                          'method of ' + self.repr(object.im_self) or
!                         ' unbound %s method' % object.im_class.__name__)
              object = object.im_func
  
***************
*** 576,581 ****
              title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
          else:
!             title = '<strong>%s</strong> = <a name="%s">%s</a>' % (
!                 name, anchor, realname)
          if inspect.isbuiltin(object):
              argspec = '(...)'
--- 592,604 ----
              title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
          else:
!             if (cl and cl.__dict__.has_key(realname) and
!                 cl.__dict__[realname] is object):
!                 reallink = '<a href="%s">%s</a>' % (
!                     cl.__name__ + '-' + realname, realname)
!                 skipdocs = 1
!             else:
!                 reallink = realname
!             title = '<a name="%s"><strong>%s</strong></a> = %s' % (
!                 anchor, name, reallink)
          if inspect.isbuiltin(object):
              argspec = '(...)'
***************
*** 588,598 ****
                  argspec = argspec[1:-1] # remove parentheses
  
!         decl = title + argspec + note
  
!         doc = self.markup(
!             getdoc(object), self.preformat, funcs, classes, methods)
!         doc = replace(doc, ('<br>\n', '</tt></small\n><dd><small><tt>'))
!         doc = doc and '<tt>%s</tt>' % doc
!         return '<dl><dt>%s<dd>%s</dl>' % (decl, self.small(doc))
  
      def docother(self, object, name=None):
--- 611,623 ----
                  argspec = argspec[1:-1] # remove parentheses
  
!         decl = title + argspec + (note and self.small(self.grey(note)))
  
!         if skipdocs:
!             return '<dl><dt>%s</dl>' % decl
!         else:
!             doc = self.markup(
!                 getdoc(object), self.preformat, funcs, classes, methods)
!             doc = doc and '<tt>%s</tt>' % doc
!             return '<dl><dt>%s<dd>%s</dl>' % (decl, self.small(doc))
  
      def docother(self, object, name=None):
***************
*** 704,715 ****
          """Produce text documentation for a given module object."""
          name = object.__name__ # ignore the passed-in name
          lines = split(strip(getdoc(object)), '\n')
          if len(lines) == 1:
!             if lines[0]: name = name + ' - ' + lines[0]
              lines = []
          elif len(lines) >= 2 and not rstrip(lines[1]):
!             if lines[0]: name = name + ' - ' + lines[0]
              lines = lines[2:]
!         result = self.section('NAME', name)
  
          try:
--- 729,741 ----
          """Produce text documentation for a given module object."""
          name = object.__name__ # ignore the passed-in name
+         namesec = name
          lines = split(strip(getdoc(object)), '\n')
          if len(lines) == 1:
!             if lines[0]: namesec = namesec + ' - ' + lines[0]
              lines = []
          elif len(lines) >= 2 and not rstrip(lines[1]):
!             if lines[0]: namesec = namesec + ' - ' + lines[0]
              lines = lines[2:]
!         result = self.section('NAME', namesec)
  
          try:
***************
*** 792,802 ****
              title = self.bold(name) + ' = class ' + realname
          if bases:
!             parents = map(lambda c, m=object.__module__: classname(c, m), bases)
              title = title + '(%s)' % join(parents, ', ')
  
          doc = getdoc(object)
          contents = doc and doc + '\n'
!         for key, value in inspect.getmembers(object, inspect.ismethod):
!             contents = contents + '\n' + self.document(value, key, name)
  
          if not contents: return title + '\n'
--- 818,831 ----
              title = self.bold(name) + ' = class ' + realname
          if bases:
!             def makename(c, m=object.__module__): return classname(c, m)
!             parents = map(makename, bases)
              title = title + '(%s)' % join(parents, ', ')
  
          doc = getdoc(object)
          contents = doc and doc + '\n'
!         methods = allmethods(object).items()
!         methods.sort()
!         for key, value in methods:
!             contents = contents + '\n' + self.document(value, key, object)
  
          if not contents: return title + '\n'
***************
*** 807,817 ****
          return '=' + self.repr(object)
  
!     def docroutine(self, object, name=None, clname=None):
          """Produce text documentation for a function or method object."""
          realname = object.__name__
          name = name or realname
          note = ''
          if inspect.ismethod(object):
!             if not clname:
                  if object.im_self:
                      note = ' method of %s' % self.repr(object.im_self)
--- 836,855 ----
          return '=' + self.repr(object)
  
!     def docroutine(self, object, name=None, cl=None):
          """Produce text documentation for a function or method object."""
          realname = object.__name__
          name = name or realname
          note = ''
+         skipdocs = 0
          if inspect.ismethod(object):
!             if cl:
!                 if not cl.__dict__.has_key(name):
!                     base = object.im_class
!                     basename = base.__name__
!                     if base.__module__ != cl.__module__:
!                         basename = base.__module__ + '.' + basename
!                     note = ' from %s' % basename
!                     skipdocs = 1
!             else:
                  if object.im_self:
                      note = ' method of %s' % self.repr(object.im_self)
***************
*** 823,826 ****
--- 861,867 ----
              title = self.bold(realname)
          else:
+             if (cl and cl.__dict__.has_key(realname) and
+                 cl.__dict__[realname] is object):
+                 skipdocs = 1
              title = self.bold(name) + ' = ' + realname
          if inspect.isbuiltin(object):
***************
*** 835,843 ****
          decl = title + argspec + note
  
!         doc = getdoc(object)
!         if doc:
!             return decl + '\n' + rstrip(self.indent(doc)) + '\n'
!         else:
              return decl + '\n'
  
      def docother(self, object, name=None, maxlen=None):
--- 876,884 ----
          decl = title + argspec + note
  
!         if skipdocs:
              return decl + '\n'
+         else:
+             doc = getdoc(object) or ''
+             return decl + '\n' + (doc and rstrip(self.indent(doc)) + '\n')
  
      def docother(self, object, name=None, maxlen=None):
***************
*** 952,956 ****
  
  def describe(thing):
!     """Produce a short description of the given kind of thing."""
      if inspect.ismodule(thing):
          if thing.__name__ in sys.builtin_module_names:
--- 993,997 ----
  
  def describe(thing):
!     """Produce a short description of the given thing."""
      if inspect.ismodule(thing):
          if thing.__name__ in sys.builtin_module_names:
***************
*** 972,985 ****
      return type(thing).__name__
  
! def freshimp(path, cache={}):
      """Import a module, reloading it if the source file has changed."""
!     module = __import__(path)
!     if hasattr(module, '__file__'):
!         file = module.__file__
!         info = (file, os.path.getmtime(file), os.path.getsize(file))
!         if cache.has_key(path):
!             if cache[path] != info:
                  module = reload(module)
!         cache[path] = info
      return module
  
--- 1013,1037 ----
      return type(thing).__name__
  
! def freshimport(name, cache={}):
      """Import a module, reloading it if the source file has changed."""
!     topmodule = __import__(name)
!     module = None
!     for component in split(name, '.'):
!         if module == None:
!             module = topmodule
!             path = split(name, '.')[0]
!         else:
!             module = getattr(module, component)
!             path = path + '.' + component
!         if hasattr(module, '__file__'):
!             file = module.__file__
!             if os.path.exists(file):
!                 info = (file, os.path.getmtime(file), os.path.getsize(file))
!             if cache.has_key(path) and cache[path] != info:
                  module = reload(module)
!             file = module.__file__
!             if os.path.exists(file):
!                 info = (file, os.path.getmtime(file), os.path.getsize(file))
!             cache[path] = info
      return module
  
***************
*** 987,1021 ****
      """Locate an object by name (or dotted path), importing as necessary."""
      if not path: # special case: imp.find_module('') strangely succeeds
!         return None, None
      if type(path) is not types.StringType:
!         return None, path
      parts = split(path, '.')
!     n = 1
!     while n <= len(parts):
          path = join(parts[:n], '.')
          try:
!             module = freshimp(path)
          except:
!             # determine if error occurred before or after module was found
              if sys.modules.has_key(path):
!                 filename = sys.modules[path].__file__
!             elif sys.exc_type is SyntaxError:
!                 filename = sys.exc_value.filename
              else:
!                 # module not found, so stop looking
!                 break
!             # error occurred in the imported module, so report it
!             raise DocImportError(filename, sys.exc_info())
          try:
              x = module
!             for p in parts[1:]:
                  x = getattr(x, p)
!             return join(parts[:-1], '.'), x
          except AttributeError:
!             n = n + 1
              continue
      if hasattr(__builtins__, path):
!         return None, getattr(__builtins__, path)
!     return None, None
  
  # --------------------------------------- interactive interpreter interface
--- 1039,1079 ----
      """Locate an object by name (or dotted path), importing as necessary."""
      if not path: # special case: imp.find_module('') strangely succeeds
!         return None
      if type(path) is not types.StringType:
!         return path
      parts = split(path, '.')
!     n = len(parts)
!     while n > 0:
          path = join(parts[:n], '.')
          try:
!             module = freshimport(path)
          except:
!             # Did the error occur before or after the module was found?
!             (exc, value, tb) = info = sys.exc_info()
              if sys.modules.has_key(path):
!                 # An error occured while executing the imported module.
!                 raise ErrorDuringImport(sys.modules[path].__file__, info)
!             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.
!                 n = n - 1
!                 continue
              else:
!                 # Some other error occurred before executing the module.
!                 raise DocImportError(filename, sys.exc_info())
          try:
              x = module
!             for p in parts[n:]:
                  x = getattr(x, p)
!             return x
          except AttributeError:
!             n = n - 1
              continue
      if hasattr(__builtins__, path):
!         return getattr(__builtins__, path)
!     return None
  
  # --------------------------------------- interactive interpreter interface
***************
*** 1028,1037 ****
      if type(thing) is type(""):
          try:
!             path, x = locate(thing)
!         except DocImportError, value:
              print value
              return
!         if x:
!             thing = x
          else:
              print 'no Python documentation found for %s' % repr(thing)
--- 1086,1095 ----
      if type(thing) is type(""):
          try:
!             object = locate(thing)
!         except ErrorDuringImport, value:
              print value
              return
!         if object:
!             thing = object
          else:
              print 'no Python documentation found for %s' % repr(thing)
***************
*** 1047,1052 ****
      """Write HTML documentation to a file in the current directory."""
      try:
!         path, object = locate(key)
!     except DocImportError, value:
          print value
      else:
--- 1105,1110 ----
      """Write HTML documentation to a file in the current directory."""
      try:
!         object = locate(key)
!     except ErrorDuringImport, value:
          print value
      else:
***************
*** 1091,1098 ****
  def man(key):
      """Display documentation on an object in a form similar to man(1)."""
!     path, object = locate(key)
      if object:
          title = 'Python Library Documentation: ' + describe(object)
!         if path: title = title + ' in ' + path
          pager('\n' + title + '\n\n' + text.document(object, key))
          found = 1
--- 1149,1157 ----
  def man(key):
      """Display documentation on an object in a form similar to man(1)."""
!     object = locate(key)
      if object:
          title = 'Python Library Documentation: ' + describe(object)
!         lastdot = rfind(key, '.')
!         if lastdot > 0: title = title + ' in ' + key[:lastdot]
          pager('\n' + title + '\n\n' + text.document(object, key))
          found = 1
***************
*** 1150,1154 ****
              if modname != '__main__':
                  seen[modname] = 1
!                 desc = split(freshimp(modname).__doc__ or '', '\n')[0]
                  if find(lower(modname + ' - ' + desc), lower(key)) >= 0:
                      callback(None, modname, desc)
--- 1209,1213 ----
              if modname != '__main__':
                  seen[modname] = 1
!                 desc = split(freshimport(modname).__doc__ or '', '\n')[0]
                  if find(lower(modname + ' - ' + desc), lower(key)) >= 0:
                      callback(None, modname, desc)
***************
*** 1206,1215 ****
              if path and path != '.':
                  try:
!                     p, x = locate(path)
!                 except DocImportError, value:
                      self.send_document(path, html.escape(str(value)))
                      return
!                 if x:
!                     self.send_document(describe(x), html.document(x, path))
                  else:
                      self.send_document(path,
--- 1265,1274 ----
              if path and path != '.':
                  try:
!                     obj = locate(path)
!                 except ErrorDuringImport, value:
                      self.send_document(path, html.escape(str(value)))
                      return
!                 if obj:
!                     self.send_document(describe(obj), html.document(obj, path))
                  else:
                      self.send_document(path,
***************
*** 1221,1231 ****
                  def bltinlink(name):
                      return '<a href="%s.html">%s</a>' % (name, name)
!                 names = filter(lambda x: x != '__main__', sys.builtin_module_names)
                  contents = html.multicolumn(names, bltinlink)
                  indices = ['<p>' + html.bigsection(
                      'Built-in Modules', '#ffffff', '#ee77aa', contents)]
  
-                 # for skip in ['', '.', os.getcwd(), os.path.dirname(sys.argv[0])]:
-                 #     if skip in sys.path: sys.path.remove(skip)
                  seen = {}
                  for dir in pathdirs():
--- 1280,1289 ----
                  def bltinlink(name):
                      return '<a href="%s.html">%s</a>' % (name, name)
!                 names = filter(lambda x: x != '__main__',
!                                sys.builtin_module_names)
                  contents = html.multicolumn(names, bltinlink)
                  indices = ['<p>' + html.bigsection(
                      'Built-in Modules', '#ffffff', '#ee77aa', contents)]
  
                  seen = {}
                  for dir in pathdirs():
***************
*** 1454,1463 ****
      class BadUsage: pass
  
!     try:
!         if sys.platform in ['mac', 'win32'] and not sys.argv[1:]:
!             # graphical platforms with threading (and no CLI)
!             gui()
!             return
  
          opts, args = getopt.getopt(sys.argv[1:], 'gk:p:w')
          writing = 0
--- 1512,1519 ----
      class BadUsage: pass
  
!     # Scripts don't get the current directory in their path by default.
!     sys.path.insert(0, '.')
  
+     try:
          opts, args = getopt.getopt(sys.argv[1:], 'gk:p:w')
          writing = 0
***************
*** 1494,1498 ****
                  else:
                      man(arg)
!             except DocImportError, value:
                  print value
  
--- 1550,1554 ----
                  else:
                      man(arg)
!             except ErrorDuringImport, value:
                  print value