Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docstring implicit inheritance can render cross-reference targets ambiguous. #6211

Open
anntzer opened this issue Mar 27, 2019 · 1 comment

Comments

@anntzer
Copy link
Contributor

anntzer commented Mar 27, 2019

Describe the bug

When a subclass is added, implicit docstring inheritance by its methods can create ambiguous cross-reference targets in the docstrings of the methods of the parent class.

To Reproduce

Start with a minimal project:

$ sphinx-quickstart --sep --dot _ -pfoo -afoo -r0 -len --suffix .rst --master index --ext-autodoc -m

Edit index.rst to include

.. automodule:: themodule
   :members:

and write the following themodule.py:

class A:
    """The A."""

    def dothis(self):
        """Call :obj:`.dothat`."""

    def dothat(self):
        """Really do it."""


class Unrelated:
    """Nothing related."""

    def dothat(self):
        """Has the same name as :obj:`A.dothat`, but otherwise unrelated."""

Build the docs with themodule.py in the PYTHONPATH (PYTHONPATH=. make html) -- things work fine; in particular the doc of A.dothis correctly links to A.dothat.

Now let's say someone adds (in the same module) a subclass of A that overrides dothis, but doesn't bother with a docstring:

class B(A):
    def dothis(self): pass

Trying to build the docs now results in a warning:

/tmp/testdocs/themodule.py:docstring of themodule.B.dothis:1: WARNING: more than one target found for cross-reference 'dothat': themodule.A.dothat, themodule.Unrelated.dothat

i.e. B.dothis inherited A.dothis's docstring, but doesn't know what ":obj:`.dothat`" is supposed to refer to. I believe it should actually resolve it to mean B.dothat (which happens to be equal to A.dothat). (emphasis as this is the actual issue at hand) Indeed, if B also defines dothat:

class B(A):
    def dothis(self): pass
    def dothat(self): pass

then the docstring of B.dothis does link to B.dothat.

Expected behavior

In B.dothis's docstring, ":obj:`.dothat`" should link to A.dothat (if B.dothat does not exist).

Your project
n/a

Screenshots
n/a

Environment info

  • OS: linux
  • Python version: 3.7.2
  • Sphinx version: 1.8.5
  • Sphinx extensions: sphinx.ext.autodoc
  • Extra tools: n/a

Additional context
Add any other context about the problem here.

  • [e.g. URL or Ticket]
@tk0miya tk0miya added this to the 2.1.0 milestone Mar 31, 2019
@tk0miya tk0miya modified the milestones: 2.1.0, 2.2.0 Jun 1, 2019
@tk0miya tk0miya modified the milestones: 2.2.0, 2.3.0 Aug 18, 2019
@anntzer
Copy link
Contributor Author

anntzer commented Nov 17, 2019

I looked a bit into how to resolve this (and other similar issues, e.g. Derived classes in other modules losing the ability to refer to things defined in the module of the parent class). Unfortunately, it looks like by the time the references are getting resolved (in resolve_xref), the information that B derives from A (and thus that the docstrings should be resolved by preferring A) has been lost. Indeed, even when using :show-inheritance:, autodoc just formats the parent classes as

    Bases: :class:`...`

It may help if :py:class: gained the ability to record base classes, e.g.

.. py:class:: Derived
   :bases: Base, fully.qualified.base.Name

(one can't use .. py:class:: Derived(Base, ...) because parentheses specify the constructor signature).

@tk0miya tk0miya modified the milestones: 2.3.0, 2.4.0 Dec 8, 2019
@tk0miya tk0miya modified the milestones: 2.4.0, 3.0.0 Feb 7, 2020
@tk0miya tk0miya modified the milestones: 3.0.0, 3.1.0 Mar 14, 2020
@tk0miya tk0miya modified the milestones: 3.1.0, 3.2.0 May 30, 2020
@tk0miya tk0miya modified the milestones: 3.2.0, 3.3.0 Aug 2, 2020
@tk0miya tk0miya modified the milestones: 3.3.0, 4.0.0 Nov 1, 2020
@tk0miya tk0miya modified the milestones: 4.0.0, 4.1.0 Apr 17, 2021
@tk0miya tk0miya modified the milestones: 4.1.0, 4.2.0 Jul 10, 2021
@tk0miya tk0miya modified the milestones: 4.2.0, 4.3.0 Sep 12, 2021
@tk0miya tk0miya removed this from the 4.3.0 milestone Nov 9, 2021
@tk0miya tk0miya added this to the 4.4.0 milestone Nov 9, 2021
@tk0miya tk0miya modified the milestones: 4.4.0, 4.5.0 Jan 15, 2022
@tk0miya tk0miya modified the milestones: 4.5.0, 5.0.0 Mar 27, 2022
@tk0miya tk0miya modified the milestones: 5.0.0, 5.x May 15, 2022
@AA-Turner AA-Turner modified the milestones: 5.x, some future version May 23, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants