sphinx-doc / sphinx-doc/sphinx
Inheritance diagram can't import classes within a class
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 8k
- Forks
- 2.6k
- PR merge metrics
- No merged PRs in 30d
Description
Apologies if this is a duplicated issue, I searched but nothing turned up.
Problem
The inheritance diagram plugin fails to import classes within a class within a package/module.
The root-cause of the problem is the function try_import() within inheritance_diagram.py. The current implementation tries to import the full object name, and if that fails, it attempts to strip off the class/final module name, and import what was before that. This works for cases like foo_package.foo_subpackage.FooClass, but not foo_package.FooClass.BarClass.
Procedure to reproduce the problem
- Create a new python package called
foo_package, add__init__.py,docfolder, etc.. - Create a new sphinx project for
foo_packageunder/doc/ - In
conf.py, set it up to point to the new package, and addsphinx.ext.inheritance_diagramto theextensionslist. - Add the code below into
foo_packageandindex.rst:
__init__.py within foo_package:
class Foo:
class Bar:
pass
class Baz(Bar):
pass
index.rst for foo_package:
.. inheritance-diagram::
foo_package.Foo.Bar
foo_package.Foo.Baz
Error logs / results
index.rst:16: WARNING: Could not import class or module 'foo_package.Foo.Bar' specified for inheritance diagram
The function try_import() is splitting the object name into foo_package.Foo and trying to import that. Which doesn't work because it's a class.
Expected results
The inheritance diagram plugin should be able to recognize foo_package.Foo.Bar as a class 'Bar' inside class Foo, inside module foo_package.
Environment info
- OS: Windows 7
- Python version: 3.5.1
- Sphinx version: 1.8.1 (with a fix applied that prevented the released version from running with 3.5.1)
Proposed solution
Update the function try_import() within inheritance_diagram.py to correctly split the full object name at the correct point so that it contains the correct module name(s) and class/classes.
This could be done a few different ways, but I don't think a regex like the one used on line 63-65 is enough to work by itself. The one that comes to my head is to iteratively pop off attribute names off of the string until it is importable, and then return the result of getattr(sys.modules.get(modname), attrname, None).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Open inheritance_diagram.py and inspect try_import(); reproduce the failure with the nested Foo.Bar and Foo.Baz classes and the shown inheritance-diagram directive. Done means the plugin imports classes nested inside classes and no longer emits the reported warning for foo_package.Foo.Bar.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- documentation
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 45/100