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
Idle: increase max calltip width #64537
Comments
Idle calltips are currently limited to 75 (signature) or 70 (doc line) chars. This is insufficient for some stdlib signatures. Example: >>> from http.client import HTTPConnection
>>> import inspect
>>> fob=HTTPConnection.__init__
>>> line=inspect.formatargspec(*inspect.getfullargspec(fob))
>>> line, len(line)
('(self, host, port=None, strict=<object object at 0x03125148>, timeout=<object object at 0x01FF7408>, source_address=None)', 121) The truncated tip displayed is "(self, host, port=None, strict=<object object at 0x03125148>, timeout=<object obj ..." Given that Idle is a graphics application, not a 80-char text console application, there is no obvious reason for the particular restriction other that esthetics. The tip is in a popup window that is separate from the shell or editor window where '(' was typed. On my widescreen monitor, there is room for, say, 200 chars. If I move the underlying window to the far right, so there is not enough room for even the truncated "HTTPConnection(" tip, Windows just truncates it further, as with any other window. Serhiy, if you have a *nix machine, can you verify that there is no problem with that either? The limits appear in multiple places in CallTipWindow.showtip and CallTips.get_argspec. Since get_argspec truncates a docstring line to less that showtip allows, there is no ' ...' added and showtip only affects inspect signatures. Get_argspec could leave length enforcement, whatever we decide it should be, to showtip. I think the first thing to do is replace the multiple hard-coded numbers with one named constant. |
Meant to mention that wrapping is a possible alternative to truncation, although a limit of say, 200, would make either alternative rare. |
On further thought, I think the best place to truncate lines is in get_argspec, after being split from the docstring and before rejoined. |
I deleted truncation code in CallTipWindow.py, all three versions, but messed up issue number. 3.3 (same) http://hg.python.org/cpython/rev/1b89fd73c625 Issue still open for changing CallTips._MAX_COLS. |
There is no problem on Linux. I think wrapping will be more preferable. 200 columns looks to wide for tips. Perhaps in 3.4 we can use textwrap.wrap() with the max_lines argument. And left simple truncating in earlier versions. |
How about we extend the limit from 79 to say 120, to accommodate people who use longer docstring lines, and only wrap the signature line, when present, like the one for HTTPConnection, as the signature is the important information to include. |
Yes, I think we can extend the limit (until implement wrapping). On my narrow monitor there is a room only for 120 character tip (when it starts right from left side of the screen), so I prefer to wrap long lines. In any case too long lines are not comfortable to read. >>> len(str(inspect.signature(textwrap.TextWrapper)))
242 |
Here is a patch (for 3.4) which wraps long lines. Now you can display a tip for textwrap.TextWrapper. |
I want to keep the code as simple and fast as possible, and not worry much about rare oddball or PEP-8-violating cases. I want to only do what is needed for the purpose of calltips, which is to remind one of the call sequence. Adding more detracts from that purpose. Tips are not intended to replace using the doc or help(f) to learn about f. As it is, I am not happy about possibly including more than 1 or 2 lines of a docstring for Python-coded functions. I intend to revisit that when the dust settles with Clinic and inspect. That fact that another patch *will* be needed, almost certainly, is another reason to not do too much now. Wrapping overly long docstrings should not needed. Even if the initial _MAX_COL slice of the first line of the docstring of a Python-coded function fails to say enough about the return value, there is help(f) to get full details. I reread PEP-8 and, contrary to what I (mis) remembered, it says that docstrings should remain limited to 72 (or 79) chars *even if* a project increases the limit for *code* lines up to say, 100. The reason for this is precisely because other software, like help, Idle, and others, read, process, and display docstrings. If docstrings violate this, I think they should be changed, and not accomadated (except as suggested below). So I want to add, before the docstring fetch, only this: if len(argspec) > _MAX_COLS:
argspec = textwrap.wrap(argspec, _MAX_COLS,
subsequent_indent=' ') dict is definitely an oddball and I do not want to include it in a test at this time. I do not mind suggesting help(dict), though the current docstring is incomplete. Here is the real signature and description, which I verified from the examples below. The multiple example lines should follow a condensed summary. def dict([map_or_it,] **kwds)
'''Return new dictionary initialized from pairs of positional-only
map_or_it, if present, and updated with kwds, if present. <start current docstring with specifics> >>> dict({'a':1}, b=2)
{'b': 2, 'a': 1}
>>> dict({'a':1}, a=2)
{'a': 2}
First, when wrapping a signature, the 'words' after the first few typically have the form 'name=value'. They will average much longer than the average English word (4, I think). The average wrapped line length will be _MAX_COLS - half the average 'word' length. For example (one which should become a test): >>> for line in textwrap.wrap(str(signature(textwrap.TextWrapper)),
width = 85, subsequent_indent=' '):
print(line) (width=70, initial_indent='', subsequent_indent='', expand_tabs=True, The lengths, including indents, are 69, 78, 77, and 24, all <= 79. Very few signature lines, wrapped or not, will fall in [80-85]. Second, PEP-8 allows initial summary lines to be 79 chars, as they are not "flowing long blocks of text". (I verified this with Guido.) Some docstrings in the stdlib 'cheat' a few chars, and 85 will accommodate those without ever being excessively long. |
Well, do this. I think we should add several test functions with too long signatures and/or docstrings. |
And note that currently there is a bug in doc.split('\n', 5)[:_MAX_LINES]. An argument of split() should be _MAX_LINES. |
I changed 5 to _MAX_LINES. Other than trivial duplication, I think each test example should be added for a reason, because there is something different about it that might conceivably cause a failure. For example, there should be a case with more than _MAX_LINES in the docstring. But I think one is enough to make sure we split with maxsplit. And I think one text wrap is enough. The many 't#' test functions were needed for 2.x because it has 12 lines of complicated code that were replaced here by 1. The attached patch will need adjustment for 2.7 (I believe) and 3.4 (because *,... is handled better). I plan to do so when fresher. |
textwrap.TextWrapper in 3.3 doesn't have '*' and following parameters. |
I removed the incorrect * comment. Attached is a 2.7 port of the 3.3 patch. It turns out that textwrap.TextWrap in 2.7 is an old-style class. Such did not work previously because they do not have .__call__ and failed the hasattr() check, now a try:except check. In 2.7, callable(old) == True, so there must be an explicit type check. I added one in the patch. |
LGTM. But I prefer larger indent. Perhaps we need explicit tests for constructors of old- and new-style classes, with __new__, with __init__, and without __new__ and __init__. |
New changeset d960c4cabb2b by Terry Jan Reedy in branch '2.7': New changeset 7dcc19308a7b by Terry Jan Reedy in branch '3.3': New changeset f7061219303c by Terry Jan Reedy in branch 'default': |
I increased indent to 4 spaces and made it easier to change. I believe old-styles classes do not have .__new__, so test of TextWrapper will ensure that they work. Inspect.signature should have correct logic to handle .__new__, with or without .__init__. (I presume that if both are present, they must be consistent, so .__init__ should be used.) You might want to check both behavior and test file for .signature. Idle gets .signature upgrades for free when we switch, which I hope can be in a few months at worst. Programmer use of .__new__ without .__init__ is rare enough (extremely so) that I prefer to wait. As it is, switching will already mean removing some of the current logic. |
Actually, all new-style classes .__new__ and .__init__ from object if not over-ridden. The calltip code depends on the .__init__ inheritance. |
I think test_idle is failing on many build slaves following this |
On 1/28/2014 4:48 AM, Stefan Krah wrote:
The two failures I saw on the first 4 3.x bots with Idle failures are On my Win 7 machine Jan 20, 32-bit repository build just before I added the tests that now fail.
>>> list.__doc__
"list() -> new empty list\nlist(iterable) -> new list initialized from
iterable's items"
>>> list.__init__.__doc__
'x.__init__(...) initializes x; see help(type(x)) for signature'
Jan 26, 64-bit installed 3.4.0b3:
>>> list.__doc__
"list(iterable) -> new list initialized from iterable's items"
>>> list.__init__.__doc__
'Initializes self. See help(type(self)) for accurate signature.' At some point, I will switch to using inspect.signature for Idle I will re-compile and adjust the tests by the end of the day. Terry |
On 1/28/2014 8:09 AM, Terry J. Reedy wrote:
>
> Terry J. Reedy added the comment:
>
> On 1/28/2014 4:48 AM, Stefan Krah wrote:
>>
>> Stefan Krah added the comment:
>>
>> I think test_idle is failing on many build slaves following this
>> commit.
>
> The two failures I saw on the first 4 3.x bots with Idle failures are
> the result of changes in the list docstrings. I presume these are
> related to use of Argument Clinic. I knew and documented that such
> failure was a possibility.
>
> On my Win 7 machine
>
> Jan 20, 32-bit repository build just before I added the tests that now fail.
> >>> list.__doc__
> "list() -> new empty list\nlist(iterable) -> new list initialized from
> iterable's items"
> >>> list.__init__.__doc__
> 'x.__init__(...) initializes x; see help(type(x)) for signature' In rev88792, UTC 13:00 Larry fixed this mismatch by patching
and fixed fixed the first-line deletion somewhere in changes to about 30 Until I know that there is another test somewhere that docstrings are
I recompiled but will do something else instead. Terry |
Terry J. Reedy <report@bugs.python.org> wrote:
Ah, so it was a Derby accident. Let's hope things stabilize soon. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: