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

Escape combined args kwargs #7799

Merged
merged 15 commits into from Aug 6, 2020
Merged

Conversation

keewis
Copy link
Contributor

@keewis keewis commented Jun 8, 2020

numpydoc allows combining parameters:

Parameters
---------------
a, b : optional
    factors of the product

but when trying to do that with *args and **kwargs, only the * of args will be escaped. This changes that to also allow the combined form if they are separated by , .

It will also warn if someone tried something like *args, *kwargs or *args, **kwargs, **other_kwargs or **kwargs, *args (which don't really make sense), but the warning lacks location information and I also don't know how to check for warnings in tests.

I wrote this against master but I don't think it is a breaking change. Should I try to rebase onto 3.x?

@tk0miya
Copy link
Member

tk0miya commented Jun 8, 2020

I've still not read this PR yet. But please rebase this into 3.x branch if you feel this is not breaking change. The master branch is used for the next major release (4.0) and it will be released next spring. So it's not good for minor changes.

@tk0miya
Copy link
Member

tk0miya commented Jun 8, 2020

I'll review this later (maybe this weekend)

@keewis keewis force-pushed the escape-combined-args-kwargs branch from 77a8188 to 95ec45b Compare June 8, 2020 15:18
@keewis keewis changed the base branch from master to 3.x June 8, 2020 15:18
@keewis
Copy link
Contributor Author

keewis commented Jun 8, 2020

done. Is the reason why AppVeyor fails due to a change proposed in this PR?

@keewis
Copy link
Contributor Author

keewis commented Jun 29, 2020

gentle ping, @tk0miya

@tk0miya
Copy link
Member

tk0miya commented Jul 11, 2020

It seems this only works when napoleon_use_param = False. I got following output by default settings (napoleon_use_param = True).
スクリーンショット 2020-07-11 18 23 50

def func():
    """ Single line summary

    Parameters
    ----------
    arg1: str
         Extended description of arg1
    x, y: array_like
         hello
    *args, **kwargs:
        Variable length argument list and arbitrary keyword arguments.
    """

I think this is not a problem around escapes. So we need to improve napoleon module more.

@tk0miya tk0miya added this to the 3.2.0 milestone Jul 11, 2020
@keewis
Copy link
Contributor Author

keewis commented Jul 11, 2020

That's true, but I think it's a separate issue: this PR tries to avoid the "Inline strong emphasis start-string without end-string." warnings for *args, **kwargs (which I think is raised otherwise).

@tk0miya
Copy link
Member

tk0miya commented Jul 12, 2020

Yes, it's another issue. But we need to consider how fix it. At present, I think it is better to separate (copy) the attribute entry that contains multiple variables with comma to independent entries. After the change, this fix might not be needed.

@keewis
Copy link
Contributor Author

keewis commented Jul 13, 2020

that issue is because with napopleon_use_param, combined args get translated to something like:

:param x, y: description
:type x, y: array_like

and it seems that the :param: and :type: field don't work well with the comma.

I still would say that it's fine to work on these separately (this is issue has been there for a long time) and I'd be fine with merging this only after that issue has been fixed. I'd even try to do that myself, but I'd first like to finish #7690 and resolve #7908.

@keewis
Copy link
Contributor Author

keewis commented Jul 31, 2020

debugging this a bit, the issue is that sphinx.util.docfields.TypedField allows two different styles:

:param foo: description of parameter foo
:type foo:  SomeClass

and

:param SomeClass foo: description of parameter foo

so the DocFieldTransformer will try to always split the name by whitespace, even if it shouldn't:

try:
argtype, argname = fieldarg.split(None, 1)
except ValueError:
pass
else:
types.setdefault(typename, {})[argname] = \
[nodes.Text(argtype)]
fieldarg = argname

If instead this was

                try:
                    argtype, argname = fieldarg.split(None, 1)
                    if argtype.endswith(","):
                        raise ValueError
                except ValueError:
                    pass
                else:
                    types.setdefault(typename, {})[argname] = \
                        [nodes.Text(argtype)]
                    fieldarg = argname

using something like x, y would work. Would that be something you'd accept? If so, should I include that in this PR or open a new one?

Edit: I assumed that's okay and that I should include it in this PR (if not please do tell me)

@tk0miya
Copy link
Member

tk0miya commented Aug 3, 2020

I prefer to copy a parameter entry including comma to multiple entries. Because :param: and :type: field expect that its argument is a single name. What do you think about this code?

diff --git a/sphinx/ext/napoleon/docstring.py b/sphinx/ext/napoleon/docstring.py
index 95fb1e538..243127610 100644
--- a/sphinx/ext/napoleon/docstring.py
+++ b/sphinx/ext/napoleon/docstring.py
@@ -260,14 +260,18 @@ class GoogleDocstring:
         _descs = self.__class__(_descs, self._config).lines()
         return _name, _type, _descs

-    def _consume_fields(self, parse_type: bool = True, prefer_type: bool = False
+    def _consume_fields(self, parse_type: bool = True, prefer_type: bool = False,
-                        ) -> List[Tuple[str, str, List[str]]]:
+                        multiple: bool = False) -> List[Tuple[str, str, List[str]]]:
         self._consume_empty()
         fields = []
         while not self._is_section_break():
             _name, _type, _desc = self._consume_field(parse_type, prefer_type)
             if _name or _type or _desc:
+                if _name:
+                    for name in _name.split(","):
+                        fields.append((name.strip(), _type, _desc,))
+                else:
-                fields.append((_name, _type, _desc,))
+                    fields.append((_name, _type, _desc,))
         return fields

     def _consume_inline_attribute(self) -> Tuple[str, List[str]]:
@@ -675,7 +679,7 @@ class GoogleDocstring:
         return self._format_fields(_('Other Parameters'), self._consume_fields())

     def _parse_parameters_section(self, section: str) -> List[str]:
-        fields = self._consume_fields()
+        fields = self._consume_fields(multiple=True)
         if self._config.napoleon_use_param:
             return self._format_docutils_params(fields)
         else:

@keewis
Copy link
Contributor Author

keewis commented Aug 3, 2020

As long as modifying GoogleDocstring._consume_fields instead of NumpyDocstring._consume_fields was intendended, the only technical remark I do have is that we probably shouldn't split / copy if napoleon_use_param = False.

Other than that, I don't really like the duplicated entries, because if we mention x and y in the docstring this might become confusing:

    x (array-like) – description of x and y
    y (array-like) – description of x and y

and while I think we're free to deviate, that's not the way numpydoc behaves. So if possible I'd like to keep the entries combined (but I definitely understand the desire to not abuse :param: / :type:).

@keewis
Copy link
Contributor Author

keewis commented Aug 4, 2020

In order to resolve this: would you merge this without the fix (only the escape of the combined *args, **kwargs)?

We can then investigate / discuss the fix in a separate PR. I think this issue was also reported as #7780?

@keewis keewis force-pushed the escape-combined-args-kwargs branch from 00edd32 to 478ab44 Compare August 4, 2020 16:38
@tk0miya tk0miya closed this Aug 5, 2020
@tk0miya tk0miya reopened this Aug 5, 2020
@tk0miya
Copy link
Member

tk0miya commented Aug 5, 2020

the only technical remark I do have is that we probably shouldn't split / copy if napoleon_use_param = False.

Reasonable. Thank you for your advice. I'll do it in another PR.

Copy link
Contributor Author

@keewis keewis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll do it in another PR.

Just to make sure, I didn't apply the copy / split patch, yet. Is that something you'd do in that separate PR, too?

sphinx/ext/napoleon/docstring.py Show resolved Hide resolved
sphinx/ext/napoleon/docstring.py Outdated Show resolved Hide resolved
@tk0miya
Copy link
Member

tk0miya commented Aug 5, 2020

Now I just post a PR for the copy / split patch as #8056

Copy link
Member

@tk0miya tk0miya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the quick update. awesome!
I'll review this again tomorrow (with fresh eyes) and merge it soon.

@keewis
Copy link
Contributor Author

keewis commented Aug 5, 2020

sure. Also, thanks for opening the other PR for me.

@tk0miya tk0miya merged commit 64a26ff into sphinx-doc:3.x Aug 6, 2020
@tk0miya
Copy link
Member

tk0miya commented Aug 6, 2020

Merged! Thank you for your continuous contribution!

tk0miya added a commit that referenced this pull request Aug 6, 2020
@keewis keewis deleted the escape-combined-args-kwargs branch August 6, 2020 10:33
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 24, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants