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

Feature request: Automatically link inherited methods #11434

Open
erzoe opened this issue May 21, 2023 · 7 comments
Open

Feature request: Automatically link inherited methods #11434

erzoe opened this issue May 21, 2023 · 7 comments

Comments

@erzoe
Copy link

erzoe commented May 21, 2023

Describe the bug

Referencing a method defined in the parent class from a child class with :meth:`x` does not work.
It looks as it should but there is no link.

As a workaround it is possible to reference the method in the parent class directly with :meth:`~Parent.x` but that is no solution because if someone decides to override that method in the child class all links will point to a wrong method.

Issue #4600 looks related but there it was blamed on epytext which I am not using.

How to Reproduce

$ tree
.
├── docs
│   ├── conf.py
│   └── index.rst
├── main.py
└── venv
$ cat main.py
#!/usr/bin/env python3

class Parent:

	def x(self, x: int) -> int:
		'''
		Whatever
		'''
		return x * 2

class Child(Parent):

	def y(self, x: int) -> 'tuple[int, int]':
		'''
		Referencing :meth:`~Parent.x` works, referencing :meth:`x` does not work
		'''
		x = self.x(x)
		return (x, x)
$ cat docs/index.rst
.. toctree::
   :maxdepth: 2

   modules
$ cat docs/conf.py
import os, sys
sys.path.insert(0, os.path.abspath('..'))

extensions = ['sphinx.ext.autodoc']

$ sphinx-apidoc --separate -o docs/ .
Creating file docs/main.rst.
Creating file docs/modules.rst.
$ sphinx-build -M html docs/ docs/
[...]
build succeeded.

The HTML pages are in docs/html.

Environment Information

Platform:              linux; (Linux-6.2.13-arch1-1-x86_64-with-glibc2.37)
Python version:        3.10.10 (main, Mar  5 2023, 22:26:53) [GCC 12.2.1 20230201])
Python implementation: CPython
Sphinx version:        7.0.1
Docutils version:      0.20.1
Jinja2 version:        3.1.2
Pygments version:      2.15.1

Sphinx extensions

['sphinx.ext.autodoc']

Additional context

No response

@picnixz
Copy link
Member

picnixz commented May 22, 2023

This is an expected behaviour.

You need to include the inherited members as an autodoc option since otherwise :meth:`x` is actually referencing Child.x. Since the inherited members are not shown by default, a reference to Child.x will obviously fail to render.

@erzoe
Copy link
Author

erzoe commented May 22, 2023

Thank you very much for your tip that I could work around this by adding autodoc_default_options = {'inherited-members': True} to conf.py [documentation]. That would work. But actually I think it's a reasonable default that sphinx does not duplicate equal documentation and I would like to keep that.

I can use self.x in methods of Child and therefore I would have expected that I can use :meth:`x` in the doc strings of these methods. And if inherited members is False and the documentation of Child.x is in Parent.x then I would have expected that sphinx creates a link to Parent.x.

@picnixz
Copy link
Member

picnixz commented May 22, 2023

I recall that you could actually document using :meth:`.x` (It should work most of the time)

@erzoe
Copy link
Author

erzoe commented May 22, 2023

yes, that does what I want. Thank you very much.

@erzoe erzoe closed this as completed May 22, 2023
@erzoe
Copy link
Author

erzoe commented May 22, 2023

Is there another trick to make :meth:`Child.x` work? Of course I could write :meth:`Child.x() <Parent.x>` but that would be unreadable and difficult to maintain.

To elaborate on your "most of the time": :meth:`.x` results in a wrong link if I add another class with a method called x:

class Other:

	def x() -> None:
		pass

but at least it gives a warning in that case.

I have found the documentation for the dot syntax here.

@erzoe erzoe reopened this May 22, 2023
@picnixz
Copy link
Member

picnixz commented May 22, 2023

:meth:.x results in a wrong link

Now I remember why I removed this and re-implemented PyXRefRole. On my side I actually use :role:`::name` with :: indicating that "name" should be found in the current "context". What I essentially do is change the way PyXRefRole.process_link works by replacing (at this point) :: with the class actually implementing it (it's not perfect but it does more or less the work in general). However, the implementation is not the most efficient and I'm not confident that it'd work for arbitrary projects.

Since this is actually an expected behaviour, I would suggest you changing the title of your issue because it is more a feature that you request (namely "be able to implicitly reference something that is not documented").

@erzoe erzoe changed the title Links to inherited methods don't work Feature request: Automatically link inherited methods May 22, 2023
@electric-coder
Copy link

electric-coder commented Jul 27, 2023

Of course I could write :meth:`Child.x() <Parent.x>` but that would be unreadable and difficult to maintain.

I'd argue this is the right way of doing things, if you use an IDE it should find all mentions of the parent method when refactoring.

child class with :meth:`x` does not work.

If instead you use the abbreviated form :meth:`x` any refactoring tool is likely to confuse the name with any other occurrence of that name (it's common to repeat method names across classes).

Per Google's Python style guide 3.8.3 unless there are side effects that need to be explicitly mentioned when a method is inherited there's no need to repeat its documentation in the child classes.

:meth:`~Parent.x` but that is no solution because if someone decides to override that method in the child class all links will point to a wrong method.

If someone decides to override a method in the child class they're responsible for updating the documentation, or to know the consequences of overriding a method defined in the parent class. If you write the cross-references explicitly the user is also constrained to refactor cross-references correctly.

In conclusion when you say:

:meth:`Child.x() <Parent.x>` but that would be unreadable and difficult to maintain.

It is in fact more readable and easier to maintain overall.

@AA-Turner AA-Turner added this to the some future version milestone Aug 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants