classification
Title: comma after leading optional argument is after bracket in docs
Type: enhancement Stage: resolved
Components: Documentation Versions: Python 3.4, Python 3.3, Python 3.2, Python 2.7
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: ezio.melotti Nosy List: asvetlov, chris.jerdonek, docs@python, eric.araujo, ezio.melotti, georg.brandl, python-dev
Priority: normal Keywords: easy, needs review, patch

Created on 2012-08-31 15:57 by chris.jerdonek, last changed 2012-09-15 01:47 by ezio.melotti. This issue is now closed.

Files
File name Uploaded Description Edit
issue-15831-1.patch chris.jerdonek, 2012-09-02 22:33 review
issue-15831-2.patch chris.jerdonek, 2012-09-04 23:17 review
Messages (32)
msg169547 - (view) Author: Chris Jerdonek (chris.jerdonek) * (Python committer) Date: 2012-08-31 15:57
From docs@python.org:

"""
In a number of places we find documentation with optional leading arguments where the meta-notation (square brackets) are in the wrong place.   For example, for range, the standard doc heading says

       range([start], stop [, step])   # The comma after start should be inside the square bracket, not outside.

The same error occurs with docs for print, and for slice, for random.randrange and for random.seed, etc, etc.   This seems a consistent bug whenever a function or method takes an optional first argument, and it looks like it might have been put there by some tool that generates the docs.

I use Python 3 - perhaps there was once a time when one had to supply the comma if one omitted the first argument?   In Python 3 it gives errors if one follows the documentation carefully and uses the comma.
""""

(or see http://mail.python.org/pipermail/docs/2012-August/010051.html )
msg169549 - (view) Author: Chris Jerdonek (chris.jerdonek) * (Python committer) Date: 2012-08-31 16:11
Do we know that this is easy?  It might be a Sphinx issue, in which case it might not be as trivial as fixing typos.

I ask because the reST file looks correct (for range() for example):

.. function:: range([start,] stop[, step])
msg169550 - (view) Author: Ezio Melotti (ezio.melotti) * (Python committer) Date: 2012-08-31 16:15
I thought that was just a matter of finding the wrong commas and fixing them, but if they are correct in the source, then the situation might be a bit more complicated.

Does this happen only with "unusual" signatures like range([start], stop [, step])?

FWIW this could be replaced with:
range(stop)
range(start, stop [, step])
msg169553 - (view) Author: Chris Jerdonek (chris.jerdonek) * (Python committer) Date: 2012-08-31 16:21
This is what my search for ",] " gave me (though the OP's print and random.seed do not show up in this list):

library/curses.rst
380:.. function:: newwin([nlines, ncols,] begin_y, begin_x)
659:.. method:: window.addch([y, x,] ch[, attr])
673:.. method:: window.addnstr([y, x,] str, n[, attr])
679:.. method:: window.addstr([y, x,] str[, attr])
766:.. method:: window.chgat([y, x, ] [num,] attr)
815:.. method:: window.derwin([nlines, ncols,] begin_y, begin_x)
909:.. method:: window.hline([y, x,] ch, n)
943:.. method:: window.insch([y, x,] ch[, attr])
964:.. method:: window.insnstr([y, x,] str, n [, attr])
1156:.. method:: window.subpad([nlines, ncols,] begin_y, begin_x)
1162:.. method:: window.subwin([nlines, ncols,] begin_y, begin_x)
1219:.. method:: window.vline([y, x,] ch, n)

library/functions.rst
1064:.. function:: range([start,] stop[, step])
1129:.. function:: slice([start,] stop[, step])

library/itertools.rst
55::func:`islice`          seq, [start,] stop [, step]     elements from seq[start:stop:step]                  ``islice('ABCDEFG', 2, None) --> C D E F G``
404:.. function:: islice(iterable, [start,] stop [, step])

library/random.rst
96:.. function:: randrange([start,] stop[, step])

library/syslog.rst
20:.. function:: syslog([priority,] message)

library/tkinter.tix.rst
507:.. method:: tixCommand.tix_configure([cnf,] **kw)
msg169555 - (view) Author: Andrew Svetlov (asvetlov) * (Python committer) Date: 2012-08-31 16:32
Yes, it looks like Sphinx problem.

About having tho signatures for single function/method.
Does Sphinx support it for *.. function::*?
Pointing to anchor for first signature with adding second one somewhere in paragraph text doesn't look good.
msg169557 - (view) Author: Ezio Melotti (ezio.melotti) * (Python committer) Date: 2012-08-31 16:45
> Does Sphinx support it for *.. function::*?

I'm pretty sure it does for methods, so I don't see why it shouldn't work for functions.
msg169559 - (view) Author: Andrew Svetlov (asvetlov) * (Python committer) Date: 2012-08-31 16:48
No, methods for *curses* are also corrupted.
msg169561 - (view) Author: Ezio Melotti (ezio.melotti) * (Python committer) Date: 2012-08-31 16:49
> This is what my search for ",] " gave me

It would be fine with me to use a double signature for these.

Georg, do you have any opinion?

(The double signature might be easier to understand, but the original issue should probably be fixed in Sphinx, even if we decide to stop using this kind of signature.)
msg169562 - (view) Author: Ezio Melotti (ezio.melotti) * (Python committer) Date: 2012-08-31 16:51
> No, methods for *curses* are also corrupted.

I meant the double signature support.
msg169563 - (view) Author: Chris Jerdonek (chris.jerdonek) * (Python committer) Date: 2012-08-31 16:57
> It would be fine with me to use a double signature for these.

Just an FYI that more than two signatures would be needed for cases like this:

766:.. method:: window.chgat([y, x, ] [num,] attr)
msg169565 - (view) Author: Ezio Melotti (ezio.melotti) * (Python committer) Date: 2012-08-31 16:59
> 766:.. method:: window.chgat([y, x, ] [num,] attr)

What's this even supposed to mean?

See also #14783.
msg169566 - (view) Author: Chris Jerdonek (chris.jerdonek) * (Python committer) Date: 2012-08-31 17:04
> What's this even supposed to mean?

I started wondering the same thing after I posted. :)

I guess my point/question is: are there any cases where more than two signatures would be needed to account for all of the possibilities?
msg169568 - (view) Author: Ezio Melotti (ezio.melotti) * (Python committer) Date: 2012-08-31 17:11
I think/hope that all the APIs we have in the stdlib are sane enough to have no more than 2-3 signatures (I'm not counting optional args (at the end) here).  If that's not the case we should still be able to add as many signature as we need (I don't know if Sphinx has some limit about it though).
msg169647 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2012-09-01 17:07
+1 for multiple signatures.
msg169649 - (view) Author: Chris Jerdonek (chris.jerdonek) * (Python committer) Date: 2012-09-01 17:30
> (The double signature might be easier to understand, but the original issue should probably be fixed in Sphinx, even if we decide to stop using this kind of signature.)

I filed an issue for this in the Sphinx tracker here:

https://bitbucket.org/birkenfeld/sphinx/issue/1001/comma-after-leading-optional-argument-in
msg169652 - (view) Author: Chris Jerdonek (chris.jerdonek) * (Python committer) Date: 2012-09-01 17:37
I will prepare a patch (multiple signatures, for the Python fix).
msg169696 - (view) Author: Chris Jerdonek (chris.jerdonek) * (Python committer) Date: 2012-09-02 13:42
Something to be aware of that may or may not affect the patch I'm preparing:

One reason that Sphinx seems able to render some of the more complicated function signatures is that it has logic to bail and print the parameter list verbatim from the reST file whenever its record-keeping logic becomes internally inconsistent:

except IndexError:
    # if there are too few or too many elements on the stack, just give up
    # and treat the whole argument list as one argument, discarding the
    # already partially populated paramlist node

https://bitbucket.org/birkenfeld/sphinx/src/1f3a2749df39/sphinx/domains/python.py#cl-74

This seems to come into play, for example, when rendering--

sorted(iterable[, key][, reverse])

http://docs.python.org/dev/library/functions.html#sorted
msg169697 - (view) Author: Chris Jerdonek (chris.jerdonek) * (Python committer) Date: 2012-09-02 13:47
Here are a couple functions that may need a fix different from multiple signatures:

print([object, ...], *, sep=' ', end='\n', file=sys.stdout, flush=False)

http://docs.python.org/dev/library/functions.html#print

class argparse.ArgumentParser([description][, epilog][, prog][, usage][, add_help][, argument_default][, parents][, prefix_chars][, conflict_handler][, formatter_class])

http://docs.python.org/dev/library/argparse.html#argparse.ArgumentParser
msg169709 - (view) Author: Chris Jerdonek (chris.jerdonek) * (Python committer) Date: 2012-09-02 16:36
FWIW, I submitted a patch for the Sphinx issue I created:

https://bitbucket.org/birkenfeld/sphinx/issue/1001

Ironically, that patch was probably easier than this patch will be.
msg169726 - (view) Author: Chris Jerdonek (chris.jerdonek) * (Python committer) Date: 2012-09-02 22:33
Attaching a proposed patch for the default branch.  Also, here are several comments and questions.

> I think/hope that all the APIs we have in the stdlib are sane enough to have no more than 2-3 signatures

I found this one in the curses module with four:

window.chgat(attr)
window.chgat(num, attr)
window.chgat(y, x, attr)
window.chgat(y, x, num, attr)

Do we like how these look?  Is the bare star notation too obscure?

inspect.Signature.replace(*[, parameters][, return_annotation])
inspect.Parameter.replace(*[, name][, kind][, default][, annotation])

I was curious what the preferred way to display the following is, since I don't think any comma/bracket placement will work:

ArgumentParser([description][, epilog][, prog][, usage][, add_help][, argument_default][, parents][, prefix_chars][, conflict_handler][, formatter_class])

(unless perhaps we use the construction "ArgumentParser(*[, description][, epilog]....")

I'm not sure how we want to handle this one using multiple signatures:

multiprocessing.Process([group[, target[, name[, args[, kwargs]]]]], *, daemon=None)

I put my preferred rendering in the patch, but Sphinx re-renders it in its own way.

I also noticed these more unusual signatures:

urllib.request.urlopen(url, data=None[, timeout], *, cafile=None, capath=None, cadefault=True)
http.client.HTTPSConnection(host, port=None, key_file=None, cert_file=None[, strict[, timeout[, source_address]]], *, context=None, check_hostname=None)

By the way, is the * really necessary in these examples?
msg169828 - (view) Author: Ezio Melotti (ezio.melotti) * (Python committer) Date: 2012-09-04 13:10
> Do we like how these look?  Is the bare star notation too obscure?
>
> inspect.Signature.replace(*[, parameters][, return_annotation])
> inspect.Parameter.replace(*[, name][, kind][, default][, annotation])

Note that if possible, it's better to avoid using the [] and put the default values.  However, in these cases the default value seems to be a _void placeholder.

The star notation is OK, since it's valid Python.


> I was curious what the preferred way to display the following is,
> since I don't think any comma/bracket placement will work:
>
> ArgumentParser([description][, epilog][, prog][, usage][, add_help][, argument_default][, parents][, prefix_chars][, conflict_handler][, formatter_class])

If the default values are known you could use them, otherwise this signature looks OK to me.

> (unless perhaps we use the construction "ArgumentParser(*[, 
> description][, epilog]....")

This is OK too, as long as all the arguments (including 'description') are keyword-only.

> I'm not sure how we want to handle this one using multiple signatures:
>
> multiprocessing.Process([group[, target[, name[, args[, kwargs]]]]], *, daemon=None)

This is OK too.

> I also noticed these more unusual signatures:
>
> urllib.request.urlopen(url, data=None[, timeout], *, cafile=None, capath=None, cadefault=True)
> http.client.HTTPSConnection(host, port=None, key_file=None, cert_file=None[, strict[, timeout[, source_address]]], *, context=None, check_hostname=None)

Here the args between [] probably have a placeholder default, or are obtained from somewhere else (e.g. from socket.getdefaulttimeout()).  These signature, albeit a bit weird, are understandable IMHO, so, unless you find a better way to write them, I would leave them as they are.

> By the way, is the * really necessary in these examples?

If the args on the right of the * are keyword-only and the one on the left aren't, then yes.
msg169832 - (view) Author: Chris Jerdonek (chris.jerdonek) * (Python committer) Date: 2012-09-04 13:35
Thanks for responding to all of those questions, Ezio.  I will update the patch based on your responses.  (Likely most of it will remain the same.)

> Note that if possible, it's better to avoid using the [] and put the default
> values.  However, in these cases the default value seems to be a _void
> placeholder.

Yes, the defaults are "private" in those cases (and in I think pretty much all cases in the patch in which []'s rather than a default value are used to display keyword arguments).

> > I was curious what the preferred way to display the following is,
> > since I don't think any comma/bracket placement will work:
> >
> > ArgumentParser([description][, epilog][, prog][, usage][, add_help][, argument_default][, parents][, prefix_chars][, conflict_handler][, formatter_class])

> If the default values are known you could use them, otherwise this signature looks OK to me.

The comma not being inside the first bracket is what I was concerned about here (which was the issue raised in the original comment).  Using an initial * which you are okay with will address this.  (And yes, they are all keyword arguments.  In fact, the order of the arguments in the docs does not even match the order in the code.)

> > By the way, is the * really necessary in these examples?

> If the args on the right of the * are keyword-only and the one on the left aren't, then yes.

Okay.  I think what threw me is that I don't think we're consistently using the * throughout our docs to denote the beginning of keyword-only arguments.  The ArgumentParser constructor above is just one example.  So I wasn't sure if this notation was preferred or discouraged.
msg169836 - (view) Author: Ezio Melotti (ezio.melotti) * (Python committer) Date: 2012-09-04 16:26
> So I wasn't sure if this notation was preferred or discouraged.

We are moving toward using the same signatures that we have in the Python code, but that doesn't always work (e.g. when the meaning of values changes depending on the number of args, when there's some trick with *args/**kwargs involved, when there are default placeholders, etc.).
The single * is not so common (yet), and it might be difficult to understand for new users, that's why I said it's OK to leave it out in cases where all the args are keyword args and the [] are used.
msg169844 - (view) Author: Chris Jerdonek (chris.jerdonek) * (Python committer) Date: 2012-09-04 23:17
Attaching an updated patch after doing another pass at the code and in light of Ezio's comments.

Let me know if and when you'd like me to prepare separate patches for 2.7 and 3.2.
msg169851 - (view) Author: Chris Jerdonek (chris.jerdonek) * (Python committer) Date: 2012-09-05 00:46
> We are moving toward using the same signatures that we have in the Python code....  The single * is not so common (yet),

I created issue 15865 to add the single * to the documentation where appropriate.
msg170471 - (view) Author: Roundup Robot (python-dev) Date: 2012-09-14 04:00
New changeset b01eb870f84f by Ezio Melotti in branch '3.2':
#15831: document multiple signatures on different lines.  Patch by Chris Jerdonek.
http://hg.python.org/cpython/rev/b01eb870f84f

New changeset 0ed61ee823d8 by Ezio Melotti in branch 'default':
#15831: merge with 3.2
http://hg.python.org/cpython/rev/0ed61ee823d8

New changeset 2291aff20a05 by Ezio Melotti in branch '2.7':
#15831: document multiple signatures on different lines.  Patch by Chris Jerdonek.
http://hg.python.org/cpython/rev/2291aff20a05
msg170472 - (view) Author: Ezio Melotti (ezio.melotti) * (Python committer) Date: 2012-09-14 04:03
Fixed, thanks for the patch!
msg170493 - (view) Author: Chris Jerdonek (chris.jerdonek) * (Python committer) Date: 2012-09-14 17:18
Thanks, Ezio!

By the way, I didn't do a thorough check, but I noticed this difference in the 2.7 application of the patch.  The *key* argument for max() needs to be marked keyword-only.  This difference doesn't exist for the min() function.  Or are we not using the "bare *" notation in the 2.7 docs?  If not, the min() docs need to be changed instead (and possibly in several other places).

Default branch:

-.. function:: max(iterable[, args...], *[, key])
+.. function:: max(iterable, *[, key])
+              max(arg1, arg2, *args[, key])

2.7 branch:

-.. function:: max(iterable[, args...][key])
+.. function:: max(iterable[, key])
+              max(arg1, arg2, *args[, key])
msg170495 - (view) Author: Chris Jerdonek (chris.jerdonek) * (Python committer) Date: 2012-09-14 17:33
Someone pointed out that keyword-only arguments were introduced only in 3.0, but I'm not sure whether that means we can't use them as a notational device in the 2.7 docs.
msg170499 - (view) Author: Chris Jerdonek (chris.jerdonek) * (Python committer) Date: 2012-09-15 01:10
Since the bare * notation wasn't added until 3.0, my guess is that we want to remove the * below (from the 2.7 application of the patch) rather than adding it back in the max() function I pasted above:

-.. function:: min(iterable[, args...][key])
+.. function:: min(iterable, *[, key])
+              min(arg1, arg2, *args[, key])
msg170500 - (view) Author: Roundup Robot (python-dev) Date: 2012-09-15 01:46
New changeset 881acdf9133f by Ezio Melotti in branch '2.7':
#15831: avoid using 3.x syntax for keyword-only args.
http://hg.python.org/cpython/rev/881acdf9133f
msg170501 - (view) Author: Ezio Melotti (ezio.melotti) * (Python committer) Date: 2012-09-15 01:47
The * is not supposed to be used on 2.7, but I missed that.
Thanks for noticing!
History
Date User Action Args
2012-09-15 01:47:48ezio.melottisetstatus: open -> closed
type: behavior -> enhancement
messages: + msg170501

resolution: fixed
stage: needs patch -> resolved
2012-09-15 01:46:12python-devsetmessages: + msg170500
2012-09-15 01:10:31chris.jerdoneksetstatus: closed -> open
resolution: fixed -> (no value)
messages: + msg170499

stage: resolved -> needs patch
2012-09-14 17:33:52chris.jerdoneksetmessages: + msg170495
2012-09-14 17:18:43chris.jerdoneksetmessages: + msg170493
2012-09-14 04:03:44ezio.melottisetstatus: open -> closed
messages: + msg170472

assignee: docs@python -> ezio.melotti
resolution: fixed
stage: patch review -> resolved
2012-09-14 04:00:33python-devsetnosy: + python-dev
messages: + msg170471
2012-09-05 00:46:10chris.jerdoneksetmessages: + msg169851
2012-09-04 23:17:16chris.jerdoneksetfiles: + issue-15831-2.patch

messages: + msg169844
2012-09-04 16:26:15ezio.melottisetmessages: + msg169836
2012-09-04 13:35:35chris.jerdoneksetmessages: + msg169832
2012-09-04 13:10:29ezio.melottisetmessages: + msg169828
2012-09-02 22:33:53chris.jerdoneksetkeywords: + needs review, patch
files: + issue-15831-1.patch
messages: + msg169726

stage: needs patch -> patch review
2012-09-02 16:36:57chris.jerdoneksetmessages: + msg169709
2012-09-02 13:47:19chris.jerdoneksetmessages: + msg169697
2012-09-02 13:42:17chris.jerdoneksetmessages: + msg169696
2012-09-01 17:37:54chris.jerdoneksetmessages: + msg169652
2012-09-01 17:30:04chris.jerdoneksetmessages: + msg169649
2012-09-01 17:07:05georg.brandlsetmessages: + msg169647
2012-08-31 17:11:22ezio.melottisetmessages: + msg169568
2012-08-31 17:04:11chris.jerdoneksetmessages: + msg169566
2012-08-31 16:59:32ezio.melottisetmessages: + msg169565
2012-08-31 16:57:03chris.jerdoneksetmessages: + msg169563
2012-08-31 16:51:26ezio.melottisetmessages: + msg169562
2012-08-31 16:49:58ezio.melottisetnosy: + georg.brandl, eric.araujo
messages: + msg169561
2012-08-31 16:48:39asvetlovsetmessages: + msg169559
2012-08-31 16:45:25ezio.melottisetmessages: + msg169557
2012-08-31 16:32:14asvetlovsetmessages: + msg169555
2012-08-31 16:21:27chris.jerdoneksetmessages: + msg169553
2012-08-31 16:15:34ezio.melottisetmessages: + msg169550
2012-08-31 16:11:42chris.jerdoneksetmessages: + msg169549
2012-08-31 16:07:38asvetlovsetnosy: + asvetlov
2012-08-31 15:58:22ezio.melottisetkeywords: + easy
nosy: + ezio.melotti
stage: needs patch

versions: + Python 3.4
2012-08-31 15:57:14chris.jerdonekcreate