Issue #206 resolved

pydoc coverage.coverage fails with an error

Marius Gedminas
created an issue

I'm not sure if this is something strange coverage does to sys.path, or a bug in Python's pydoc.py, but

$ pydoc coverage.coverage
Traceback (most recent call last):
  File "/usr/bin/pydoc", line 5, in <module>
    pydoc.cli()
  File "/usr/lib/python2.7/pydoc.py", line 2327, in cli
    help.help(arg)
  File "/usr/lib/python2.7/pydoc.py", line 1792, in help
    elif request: doc(request, 'Help on %s:')
  File "/usr/lib/python2.7/pydoc.py", line 1531, in doc
    pager(render_doc(thing, title, forceload))
  File "/usr/lib/python2.7/pydoc.py", line 1505, in render_doc
    object, name = resolve(thing, forceload)
  File "/usr/lib/python2.7/pydoc.py", line 1496, in resolve
    object = locate(thing, forceload)
  File "/usr/lib/python2.7/pydoc.py", line 1471, in locate
    nextmodule = safeimport(join(parts[:n+1], '.'), forceload)
  File "/usr/lib/python2.7/pydoc.py", line 300, in safeimport
    raise ErrorDuringImport(sys.modules[path].__file__, info)
AttributeError: 'NoneType' object has no attribute '__file__'

Comments (4)

  1. Marius Gedminas reporter
    • edited description
    • changed component to docs
    • marked as minor
    • changed version to 3.5.3

    I've been trying to debug this for about 15 minutes before I got lost. I got as far as noticing

    >>> import sys
    >>> import coverage.nosuchmodule
    ImportError: ...
    >>>> sys.modules['coverage.nosuchmodule']
    KeyError: 'coverage.nosuchmodule'
    

    but

    >>> import coverage.coverage
    ImportError: ...
    >>> print sys.modules['coverage.coverage']
    None
    

    and this makes pydoc think coverage.coverage is a real Python module.

  2. Ned Batchelder repo owner

    An interesting bug!

    The problem is that this line at the top of coverage/__init__.py adds the None entry to sys.modules['coverage.coverage']:

    from coverage.control import coverage
    

    This is because "from coverage..." could be a submodule of the current file, but it is not. In fact, "from coverage.fooey import booey" would also add that entry.

    This can be fixed by adding this to the end of coverage/__init__.py:

    import sys
    del sys.modules['coverage.coverage']
    

    But is there a better way to avoid this? Am I importing things wrong in coverage/__init__.py?

  3. Marius Gedminas reporter

    No idea! For the record, I've tried to see if adding a from __future__ import absolute_import at the top would fix this, and the answer is: no, it doesn't.

  4. Log in to comment