133

I want to add a link to a method in my class from within the docstring of another method of the same class. I want the link to work in Sphinx and preferentially also in Spyder and other Python IDEs.

I tried several options and found only one that works, but it's cumbersome.

Suppose the following structure in mymodule.py

def class MyClass():
    def foo(self):
        print 'foo'
    def bar(self):
        """This method does the same as <link to foo>"""
        print 'foo'

I tried the following options for <link to foo>:

  • :func:`foo`
  • :func:`self.foo`
  • :func:`MyClass.foo`
  • :func:`mymodule.MyClass.foo`

The only one that effectively produces a link is :func:`mymodule.MyClass.foo` , but the link is shown as mymodule.MyClass.foo() and I want a link that is shown as foo() or foo. None of the options above produces a link in Spyder.

bad_coder
  • 11,289
  • 20
  • 44
  • 72
saroele
  • 9,481
  • 10
  • 29
  • 39
  • What does mean _"add ... from within"_ ??? What's the difference between a link and an hyperlink ? – eyquem Jan 22 '14 at 17:40
  • I replaced `hyperlink` by `link` to avoid confusion. – saroele Jan 22 '14 at 21:31
  • I still don't understand very well your question. Do you mean that you want to perform , from Sphinx or from Spyder or from others Python IDEs, an interrogation of the docstring of the function ``bar`` that will give the information _"the function or method you search is foo"_ ? – eyquem Jan 22 '14 at 21:42
  • Secondly, what difference do you make between ``mymodule.MyClass.foo()`` and ``foo()`` ? And what do you call _"display"_ ? Is it the display of a string ? Or do you want an object returned ? In this latter case, the paens at the end of ``mymodule.MyClass.foo()`` and ``foo()`` are too much. – eyquem Jan 22 '14 at 21:45
  • Sorry for the confusion, it's always hard to explain a question concisely. I just want to have a link you can click, that will take you to the docstring of foo() (in the documentation window of the IDE, or in the html build of Sphinx). Regarding the parentheses: they are correct: :func:`mymodule.MyClass.foo` resulted in the link having the parentheses. And I have rephrased the question slightly again. – saroele Jan 22 '14 at 22:12

3 Answers3

143

The solution that works for Sphinx is to prefix the reference with ~.

Per the Sphinx documentation on Cross-referencing Syntax,

If you prefix the content with ~, the link text will only be the last component of the target. For example, :py:meth:`~Queue.Queue.get` will refer to Queue.Queue.get but only display get as the link text.

So the answer is:

class MyClass():
    def foo(self):
        print 'foo'
    def bar(self):
        """This method does the same as :func:`~mymodule.MyClass.foo`"""
        print 'foo'

This results in an HTML looking like this : This method does the same as foo(), and foo() is a link.

However, note that this may not display in Spyder as a link.

bad_coder
  • 11,289
  • 20
  • 44
  • 72
saroele
  • 9,481
  • 10
  • 29
  • 39
  • 22
    (*Spyder dev here*) @saroele I plan to improve this situation in the future. I totally agree it'd be really cool to have it ;) – Carlos Cordoba Jan 24 '14 at 04:05
  • You can do it with the [`:any:` role](http://sphinx-doc.org/markup/inline.html#role-any) - see the note about `default_setting`. – naught101 Aug 27 '15 at 03:14
  • 2
    is it possible to cross-reference without using the full module path? – Jonathan Sep 26 '17 at 13:18
  • @Jonathan : in the autodoc.rst I use the currentmodule : .. currentmodule:: mymodule .. autosummary:: mymodule.MyClass and in the docstring, using simply the short name is ok. – Demi-Lune Apr 13 '18 at 16:28
  • 1
    It seems `:func:\`~foo\`` will do, if that foo() method is within the same class as current method bar(). – RayLuo Dec 19 '18 at 09:13
  • 5
    Instead of `:func:`, I found it has to be `:meth:`. – Leo Fang Jul 26 '19 at 01:37
56

If you want to manually specify the text of the link you can use:

:func:`my text <mymodule.MyClass.foo>`

For more information, checkout Cross-referencing Python objects.

dan
  • 37
  • 1
  • 8
devin_s
  • 3,345
  • 1
  • 27
  • 32
  • This works, thanks. By looking at the link, I found out that prefixing the reference with ``~`` is closer to what I need. I have put that in a separate answer. It still doesn't work in Spyder however... – saroele Jan 23 '14 at 00:50
-9

It seems to me that you just have to add __name__ or __doc__ to your expression to obtain what you want.
I'm still not sure to have correctly understood the aim

class MyClass():
    def foo(self):
        """I am the docstring of foo"""
        print 'foo'
    def bar(self):
        """This method does the same as <link to foo>"""
        print 'foo'

print
print MyClass.foo
print MyClass.foo.__name__
print MyClass.foo.__doc__
print
print MyClass.__dict__['foo']
print MyClass.__dict__['foo'].__name__
print MyClass.__dict__['foo'].__doc__

result

<unbound method MyClass.foo>
foo
I am the docstring of foo

<function foo at 0x011C27B0>
foo
I am the docstring of foo
eyquem
  • 26,771
  • 7
  • 38
  • 46
  • 3
    I think you missed the point of the question: I want to have a link (hyperlink) in the html of my documentation built by Sphinx. – saroele Jan 23 '14 at 00:36
  • You are right, I miss the point. And that's because I don't know Sphinx. so I tried to install Sphinx. But I didn't succeed. I'm on Windows and I tried to use sphinx-quickstart as said in the doc. But I think I have a misunderstanding of the intsallation process. I can't help you , sorry. I dunno what must be undertsood by 'hyperlink' in the context of Sphinx. – eyquem Jan 23 '14 at 03:19