spyder-ide / spyder

Official repository for Spyder - The Scientific Python Development Environment
https://www.spyder-ide.org
MIT License
8.14k stars 1.58k forks source link

Add option to use Napoleon to render docstrings in the object inspector #2046

Open spyder-bot opened 9 years ago

spyder-bot commented 9 years ago

From battm...@gmail.com on 2014-11-12T12:55:14Z

Not sure if this has been mentioned before. I prefer google style code commenting and was wondering if it would be possible to add an option to configure the object inspector to use sphinxcontrib.napoleon.

Poking around at the internals of the application I believe this would require packing napoleon within the sphinx extensions folder and providing option that alters the sphinx config.py file in this manner: https://pypi.python.org/pypi/sphinxcontrib-napoleon#getting-started

Original issue: http://code.google.com/p/spyderlib/issues/detail?id=2046

spyder-bot commented 9 years ago

From ccordoba12 on 2014-11-12T10:06:38Z

I know about this extension and it seems pretty cool because it allows also to render NumPy style docstrings too.

I'll think about it for 2.4

Summary: Add option to use Napoleon to render docstrings in the object inspector (was: Add option to use Napoleon to render object inspector)
Status: Accepted
Labels: MS-v2.4

spyder-bot commented 9 years ago

From ccordoba12 on 2014-11-18T14:44:46Z

Labels: Cat-ObjectInspector

randallpittman commented 7 years ago

Just now playing around with napoleon. I tested using it to document numpy.absolute and it looks nice. However, I couldn't figure out how to turn it on in Spyder 3. I added the following to my existing site-packages/spyder/utils/help/conf.py, from the Sphinx site, but it didn't render any differently in the Help pane.

extensions.append('sphinx.ext.napoleon')
# Napoleon settings
napoleon_google_docstring = True
napoleon_numpy_docstring = True
napoleon_include_private_with_doc = False
napoleon_include_special_with_doc = True
napoleon_use_admonition_for_examples = False
napoleon_use_admonition_for_notes = False
napoleon_use_admonition_for_references = False
napoleon_use_ivar = False
napoleon_use_param = True
napoleon_use_rtype = True

Maybe it should go elsewhere, or more needs to be done to enable it? I'd be happy to see it included, or at least know how to enable it.

mgaree commented 6 years ago

I spent the day trying to kludge Napoleon into the process for displaying documentation in Spyder's Help window. @silentquasar's approach doesn't work because normally Napoleon only runs when Autodoc (another Sphinx extension) emits a certain event. Since Sphinx is being called by Spyder on just a docstring instead of a whole project, it looks like Autodoc is never used. Also, I believe Napoleon relies on context from the function/module in order to format things nicely (e.g. if the docstring is from a function or class), and Spyder doesn't provide that context to Sphinx, only a docstring.

I am able to get Napoleon to process docstrings in Numpy & Google style, but they look no good when rendered in the Help window, e.g.

param param1: The first parameter. type param1: int ...

So Napoleon parses everything into RST correctly, but Spyder+Sphinx doesn't render it into what I was expecting. For anyone interested, I added the following setup() method to spyder/utils/help/conf.py. I found this to be the least invasive and most successful option for hacking the sphinxify process.

# location: spyder/utils/help/conf.py
def setup(app):
    """Replacing docutils.parsers.rst.Parser.parse to pre-process text with 
Napoleon before normal RST parsing.

    If you instead subclass the parser and use `source_parsers`, you will have 
problems when Sphinx.environment tries to pickle it.

    No other references to Napoleon are needed in spyder.utils.help.conf.
    """
    import sphinx.parsers

    def _newparse(self, inputstring, document):
        """Override of docutils.parsers.Parser method."""
        from sphinx.ext.napoleon.docstring import GoogleDocstring, NumpyDocstring

        preprocessor = GoogleDocstring(inputstring)
        inputstring = '\n'.join(preprocessor.lines())

        # The rest is copied directly from the original RST parser
        import docutils.statemachine
        from docutils.parsers.rst import states

        self.setup_parse(inputstring, document)
        self.statemachine = states.RSTStateMachine(
              state_classes=self.state_classes,
              initial_state=self.initial_state,
              debug=document.reporter.debug_flag)
        inputlines = docutils.statemachine.string2lines(
              inputstring, tab_width=document.settings.tab_width,
              convert_whitespace=True)
        self.statemachine.run(inputlines, document, inliner=self.inliner)
        self.finish_parse()

    sphinx.parsers.RSTParser.parse = _newparse

By default, Spyder Help seems to treat Numpy-style docstrings better than pure RST, so I think I'm going to switch away from Google-style for now.

ccordoba12 commented 6 years ago

So Napoleon parses everything into RST correctly, but Spyder+Sphinx doesn't render it into what I was expecting.

Please post screenshots of the current and expected results. Thanks!

mgaree commented 6 years ago

The attached images use the following source code:

min_example.py.txt

The current Spyder output is made using the default conf.py file, clicking on the function name and pressing Ctrl+I. The Napoleon+Spyder output is made by inserting setup() from my last post into conf.py (minor change to do both GoogleStyle & NumpyStyle). The stand-alone Sphinx output is made by building a Sphinx project on the above source code and the default style/theme and is what I'd call "expected output".

google-style numpy-style restructured-style

Current Spyder output is best for Numpy and is pretty perfect. Current Google-style output does not work with multiple lines in a section. Current restructuredText, the Sphinx standard, is unexpectedly poor.

My recommendation is to figure out why Spyder's sphinxify procedure doesn't handle restructuredText as-is and fix it, which would make restructuredText look good and let Napoleon be useful, or declare NumPy-style to be the only fully supported docstring standard when using Spyder.

Thanks for looking at this!