Skip to content

Anonymous return values have their types populated in the name slot of the tuple. #72

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

Closed
Erotemic opened this issue Nov 6, 2016 · 9 comments · Fixed by #175 or #176
Closed

Anonymous return values have their types populated in the name slot of the tuple. #72

Erotemic opened this issue Nov 6, 2016 · 9 comments · Fixed by #175 or #176

Comments

@Erotemic
Copy link

Erotemic commented Nov 6, 2016

I noticed an inconsistency, when using numpydoc version 0.6.0 in python2.7 on Ubuntu. The parsed return section information returns different styles of tuple depending on if the return value is anoymous or not.

Here is a minimal working example:

def mwe():
        from numpydoc.docscrape import NumpyDocString
        docstr = (
            'Returns\n'
            '----------\n'
            'int\n'
            '    can return an anoymous integer\n'
            'out : ndarray\n'
            '    can return a named value\n'
        )
        doc = NumpyDocString(docstr)
        returns = doc._parsed_data['Returns']
        print(returns)

This results in

[(u'int', '', [u'can return an anoymous integer']),
 (u'out', u'ndarray', [u'can return a named value'])]

However judging by tests (due to lack of docs), I believe it was indented that each value in the returns list should be a tuple of (arg, arg_type, arg_desc). Therefore we should see this instead:

[('', u'int', [u'can return an anoymous integer']),
 (u'out', u'ndarray', [u'can return a named value'])]

My current workaround is this:

        for p_name, p_type, p_descr in returns:
            if not p_type:
                p_name = ''
                p_type = p_name
@stefanv
Copy link
Contributor

stefanv commented Nov 13, 2016

We probably re-use the parameter section parsing here, which is a mistake. Your assessment of the problem looks correct to me.

@jnothman
Copy link
Member

How do you think this should be rendered, @Erotemic?

@Erotemic
Copy link
Author

In my minimum working example the parsing of out is rendered correctly (name, type, desc). The anonymous type should be rendered similarly, e.g. ('', 'int', 'desc'), but it is not. The type value is where the name should be.

Also note that the second part of this test, is has an error (explained in the comments), which is why its passing:

def test_returns():
    < removed first part > 

    arg, arg_type, desc = doc['Returns'][1]
    assert_equal(arg, 'list of str')   # <- the test checks that the name is the type!
    assert_equal(arg_type, '')   # <- the test checks that the type is the name!
    assert desc[0].startswith('This is not a real')
    assert desc[-1].endswith('anonymous return values.')

This probably is best handled by creating a new method in NumpyDocString called _parse_return_list that works similar to _parse_param_list, but that accounts for the case where the return name is anonymous.

Then the _parse method should be refactored to differentiate between return and param hints:

if section in ('Returns', 'Yields'):
    self[section] = self._parse_return_list(content)
elif section in ('Parameters', 'Raises',
                 'Warns', 'Other Parameters', 'Attributes',
                 'Methods'):
    self[section] = self._parse_param_list(content)
...

It would also be helpful for documentation / testing purposes if the parameter and return types were stored in a named tuple (e.g. collections.namedtuple('TypeHint', ('name', 'type', 'desc')))

Lastly, the tests will need to be fixed.

All in all, this is probably about an hour or two of work. I'd be happy to make a PR within the next week or so if this approach seems good.

@jnothman
Copy link
Member

jnothman commented Sep 12, 2017 via email

@Erotemic
Copy link
Author

Oh, I have no clue about the RST/HTML output. I've only used numpydoc for introspection purposes (i.e. in jedi). How do I see what the RST output currently looks like?

@timhoffm
Copy link
Contributor

timhoffm commented May 2, 2018

matplotlib/matplotlib#11161 contains example where this goes wrong in RST/HTML output.

@jnothman
Copy link
Member

jnothman commented May 2, 2018 via email

@timhoffm
Copy link
Contributor

timhoffm commented May 2, 2018

The numpydoc documentation claims that both of the following return parameters are supported.

Returns
-------
int
    Description of anonymous integer return value.
name : int
    Description of a named integer return value.

Expected:
I expect both ints to be recognized and formatted as types.

Obeserved:
In the first case, int is formatted as if it was a name.

Cause:
The cause was already identified by @Erotemic above. It's really that "Returns" uses the same parser as "Parameters" (_parse_param_list()). docscrape.py l.222 has
arg_name, arg_type = header, ''
which is indeed correct for "Parameters" because if there is no colon in a "Parameters" header, the header is the name. However, if there is no colon in a returns parameter, the header is the type. Hence for "Returns" (as well as "Yields", "Raises", "Warns") the correct code must be
arg_name, arg_type = '', header

Possible fix:
To make it more clear, I've written a quick PR: #175. This may need some additional work, but I hope that it makes the problem more clear already.

@timhoffm
Copy link
Contributor

timhoffm commented May 4, 2018

Please reopen. Git was too smart in interpreting fix #72 from the PR message of #176.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants