bpo-44544: [doc] list all textwrap func kwargs#26999
Conversation
* list all kwargs for `textwrap.wrap`, `textwrap.fill`, and `textwrap.shorten` * now, there are nav links to attributes of TextWrap, which makes navigation much easier while minimizing duplication
akulakov
left a comment
There was a problem hiding this comment.
Thanks! Left a few comments, nothing is wrong per se, just making it more consize..
|
@akulakov Thank you for your review! |
|
I should have mentioned I understand the attractiveness of links.. I’m a
bit on the fence on this because of it being duplicated 3 times and already
having a link to textwrapper... let me think about it a bit.
…On Fri, Jul 2, 2021 at 3:38 PM Jack DeVries ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In Doc/library/textwrap.rst
<#26999 (comment)>:
>
- See the :meth:`TextWrapper.wrap` method for additional details on how
- :func:`wrap` behaves.
+ * :attr:`.initial_indent`
The nice thing about that listing, though, is that it forms hyperlinks
directly to each of these attributes, so it makes html browsing very smooth
(see screenshot)
[image: Screen Shot 2021-07-02 at 3 38 15 PM]
<https://user-images.githubusercontent.com/58614260/124321338-86786780-db4b-11eb-938b-0e044eccea47.png>
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#26999 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAB3RITZHXANEFBG6KAHD6TTVYIUTANCNFSM47XEJQUQ>
.
|
Doc/library/textwrap.rst
Outdated
| fix_sentence_endings=False, \ | ||
| break_long_words=True, drop_whitespace=True, \ | ||
| break_on_hyphens=True, tabsize=8, \ | ||
| *, max_lines=None, **kwargs) |
There was a problem hiding this comment.
Where is placeholder? What does kwargs include?
There was a problem hiding this comment.
I thought that placeholder only has an effect in :func:shorten?
**kwargs is there just because the actual function signature is like this:
def wrap(text, width=70, **kwargs): ...Any keyword argument will be accepted, but only correctly spelled kwargs will have an effect. I added an additional note to more specifically highlight this behavior; it adds on to the paragraphs where these kwargs are listed:
Be careful not to misspell keyword arguments. Misspelled keyword arguments will silently have no effect, and an
exception will not be raised.
There was a problem hiding this comment.
I don't think that's the case, the kwargs are passed to TextWrapper, which will not accept unknown keyword args:
/usr/local/Cellar/python@3.9/3.9.1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/textwrap.py in shorten(text, width, **kwargs)
403 'Hello [...]'
404 """
--> 405 w = TextWrapper(width=width, max_lines=1, **kwargs)
406 return w.fill(' '.join(text.strip().split()))
407
TypeError: __init__() got an unexpected keyword argument 'zz'
There was a problem hiding this comment.
placeholder can apply to all 3 functions because it depends on max_lines -- if max_lines is specified and results in removing of some lines, placeholder will be added per docs.
|
If anything, I'd say maybe change the function signature back to what it originally ( |
|
The reason I didn’t like having just **kwargs in the sig is that it is
inconsistent and confusing, as I argued in the ticket, so whether the links
are kept or not, I think it’s preferable to keep the long signatures.. yes
hard to read but if we have function with many args, that’s just what you
see is what you get :)
…On Fri, Jul 2, 2021 at 4:43 PM Jack DeVries ***@***.***> wrote:
If anything, I'd say maybe change the function signature back to what it
originally (.. function:: wrap(text, width=70, **kwargs)), and keep the
links. With that many arguments, the function signature kind of looks like
spaghetti and I think that the browsing experience is much stronger with
the links.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#26999 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAB3RIRX7BYOO6JO23SN5ADTVYQGZANCNFSM47XEJQUQ>
.
|
|
A couple of thoughts: I haven't seen instances in Python docs where a list of the same links would be duplicated multiple times closely, so I feel like that doesn't match this pattern of avoiding too much repetition. An option that "splits the difference" would be to have the list of links for the first function and omit lists for the other two. I think either this option or not having links at all would work well. |
|
I saw a very similar example in current docs: https://docs.python.org/3.11/library/logging.html#logging.LoggerAdapter -- the methods are from a different class but are linked here, in one paragraph rather than separate lines. Seems like a good approach, WDYT? |
|
The few lines with inline links in the logging example look better than the list of raw names in the screenshot here, though. |
|
@merwok yep, the screenshot is outdated. We went with the list of inline links. @jdevries3133 btw Serhiy also left a few requests for change above (not sure if you saw them). |
Doc/library/textwrap.rst
Outdated
| :attr:`.drop_whitespace`, :attr:`.break_on_hyphens` :attr:`.tabsize`, and | ||
| :attr:`.max_lines`. Be careful not to misspell keyword arguments. | ||
| Misspelled keyword arguments will silently have no effect, and an exception | ||
| will not be raised. |
There was a problem hiding this comment.
In my view repetition in the docs is not better than repetition in code.
There was a problem hiding this comment.
The root cause of the repetition is that these functions all recieve a laundry list of keyword arguments, and they are all the same or highly similar. In that sense, the API is repetitive. Maybe it could have been designed better if we had dataclasses for grouping the values passed in or something like that, but I think the repetition in the documentation is a consequence of the library'a design, and we aren't going to change the API design.
There was a problem hiding this comment.
In the code, this list of args appears once in the constructor of TextWrapper. The module-level wrapper functions just forward their kwargs to this constructor. It would be enough to define all these args once and in other places say "the meaning of the parameters are the same as over there".
It's easy for these repetitions to go out of sync with each other (if you add an arg to TextWrapper.init you need to update the doc in multiple places).
I don't see what the benefit of the repetition is. For a user trying to study the library for the first time it's just tedious. For someone looking up a single function, clicking on a link to the TextWrapper constructor is not complicated.
There was a problem hiding this comment.
My preference would also be to avoid repeated list of links. I previously suggested inline links as a compromise between no links and the "tall" list with a link per line as in initial revision. I don't have a strong opinion though, as long as it's not a "tall" list.
There was a problem hiding this comment.
@iritkatriel I'm sorry, I thought you were talking about repetition between the function signature and the inline links but now I realize I don't think that's what you're talking about. I'm going to take a closer look later today, sorry for any confusion.
There was a problem hiding this comment.
@iritkatriel I see what you are saying. I went ahead and removed the repetitive links all together. Do you think that the explicit function signatures is a good change? Otherwise, there's nothing to be done here.
There was a problem hiding this comment.
Good question, I wonder if the documentation working group can come up with suggestions. This is not the only library that has this pattern. @JulienPalard @Mariatta
Doc/library/textwrap.rst
Outdated
| arguments. Note that the whitespace is collapsed before the text is passed | ||
| to the :class:`TextWrapper` :meth:`fill` function, so changing the value of | ||
| :attr:`.tabsize`, :attr:`.expand_tabs`, :attr:`.drop_whitespace`, and | ||
| :attr:`.replace_whitespace` will have no effect. Be careful not to misspell |
There was a problem hiding this comment.
The last sentence can be omitted because the same can be said for any func / method in stdlib.
|
One interesting question that I've just thought about is whether So the argument is that having **kwargs in the sig will probably only add confusion; the only utility may conceivably be that user is alerted to the idea that if they accidentally use an arg from a different function (out of these 3), it will not raise a TypeError. So it seems **kwargs is just a remnant from the old, intentionally empty sig. Thoughts? |
Doc/library/textwrap.rst
Outdated
| Wraps the single paragraph in *text* (a string) so every line is at most | ||
| *width* characters long. Returns a list of output lines, without final | ||
| newlines. | ||
| newlines. *width* defaults to ``70``. |
There was a problem hiding this comment.
Why duplicate info that is already visible in the signature?
There was a problem hiding this comment.
This is just carried over from the current doc, and not relevant to the bpo, so I left it:
https://docs.python.org/3/library/textwrap.html#textwrap.wrap
There was a problem hiding this comment.
Oh, my bad, in the old documentation, that sentence was in the docs for textwrap.wrap, and for some reason I though it'd be a good idea to bring it down here so that they match, but that's definitely not right! If anything, it'd be better to remove the unnecessary repetition from textwrap.wrap, but again, that's out of the scope of this bpo, and we can make a new little bpo for that problem after this one lands.
There was a problem hiding this comment.
Either way, I'm working on reverting all changes to things other than the function signatures right now, because I think that's all we really want to do here.
I don’t really understand what you mean here, maybe because |
I meant to say that in this particular case, **kwargs would imply to a user that they can use some other kwargs in addition to ones explicitly listed. But if they did that, they would either get a TypeError from TextWrapper, or in case of one of the functions, the kwargs they might use would be a no-op, and so should not be used. |
|
@akulakov @merwok @serhiy-storchaka @iritkatriel I went ahead and reverted any changes other than those to the documented function signature. I think that changes to the function signature are the closest to the bpo, and make the most sense to add. I think that Irit made good points about the redundant links introducing a maintainability problem and not providing a significant enough usability improvement. Andrei, I agree that documenting def __init__(self,
width=70,
initial_indent="",
subsequent_indent="",
expand_tabs=True,
replace_whitespace=True,
fix_sentence_endings=False,
break_long_words=True,
drop_whitespace=True,
break_on_hyphens=True,
tabsize=8,
*,
max_lines=None,
placeholder=' [...]'):So, you get what you would expect from a misspelled keyword argument: I had this wrong in earlier revisions of this PR, but I (mostly) fixed it in 2927e0d; "fix: incorrect information; TextWrapper.init will raise Exc," and later removed all non-function-signature changes as I mentioned above. Summary
|
|
Thanks @jdevries3133 for the PR, and @ambv for merging it 🌮🎉.. I'm working now to backport this PR to: 3.10, 3.9. |
|
GH-27424 is a backport of this pull request to the 3.10 branch. |
(cherry picked from commit c1e39d6) Co-authored-by: Jack DeVries <58614260+jdevries3133@users.noreply.github.com>
|
GH-27425 is a backport of this pull request to the 3.9 branch. |
(cherry picked from commit c1e39d6) Co-authored-by: Jack DeVries <58614260+jdevries3133@users.noreply.github.com>
textwrap.wrap,textwrap.fill, andtextwrap.shortenmuch easier while minimizing duplication
existing code.
through introspection. Maybe the mismatch is acceptable?
https://bugs.python.org/issue44544