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

argparse print_help() fails if COLUMNS is set to a low value #57929

Closed
zbysz mannequin opened this issue Jan 6, 2012 · 9 comments
Closed

argparse print_help() fails if COLUMNS is set to a low value #57929

zbysz mannequin opened this issue Jan 6, 2012 · 9 comments
Labels
stdlib Python modules in the Lib dir

Comments

@zbysz
Copy link
Mannequin

zbysz mannequin commented Jan 6, 2012

BPO 13720
Nosy @birkenfeld, @terryjreedy, @serhiy-storchaka
Superseder
  • bpo-13107: Text width in optparse.py can become negative
  • Files
  • test_argparse_narrow.py: failing testcase
  • 13720.patch
  • 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:

    assignee = None
    closed_at = <Date 2014-02-17.11:31:19.766>
    created_at = <Date 2012-01-06.13:55:48.104>
    labels = ['library']
    title = 'argparse print_help() fails if COLUMNS is set to a low value'
    updated_at = <Date 2014-02-17.11:31:19.764>
    user = 'https://bugs.python.org/zbysz'

    bugs.python.org fields:

    activity = <Date 2014-02-17.11:31:19.764>
    actor = 'serhiy.storchaka'
    assignee = 'none'
    closed = True
    closed_date = <Date 2014-02-17.11:31:19.766>
    closer = 'serhiy.storchaka'
    components = ['Library (Lib)']
    creation = <Date 2012-01-06.13:55:48.104>
    creator = 'zbysz'
    dependencies = []
    files = ['24154', '26486']
    hgrepos = []
    issue_num = 13720
    keywords = ['patch']
    message_count = 9.0
    messages = ['150733', '150782', '150785', '150786', '150787', '150789', '166102', '166188', '211408']
    nosy_count = 6.0
    nosy_names = ['georg.brandl', 'terry.reedy', 'bethard', 'zbysz', 'serhiy.storchaka', 'Russell.Sim']
    pr_nums = []
    priority = 'normal'
    resolution = 'duplicate'
    stage = 'resolved'
    status = 'closed'
    superseder = '13107'
    type = None
    url = 'https://bugs.python.org/issue13720'
    versions = ['Python 2.7', 'Python 3.3', 'Python 3.4']

    @zbysz
    Copy link
    Mannequin Author

    zbysz mannequin commented Jan 6, 2012

    % cat test_argparse_narrow.py
    import argparse
    argparse.ArgumentParser().print_help()

    % COLUMNS=15 ./python test_argparse_narrow.py
    Traceback (most recent call last):
      File "test_argparse_narrow.py", line 2, in <module>
        argparse.ArgumentParser().print_help()
      File "/home/zbyszek/python/cpython/Lib/argparse.py", line 2347, in print_help
        self._print_message(self.format_help(), file)
      File "/home/zbyszek/python/cpython/Lib/argparse.py", line 2321, in format_help
        return formatter.format_help()
      File "/home/zbyszek/python/cpython/Lib/argparse.py", line 276, in format_help
        help = self._root_section.format_help()
      File "/home/zbyszek/python/cpython/Lib/argparse.py", line 206, in format_help
        func(*args)
      File "/home/zbyszek/python/cpython/Lib/argparse.py", line 206, in format_help
        func(*args)
      File "/home/zbyszek/python/cpython/Lib/argparse.py", line 514, in _format_action
        help_lines = self._split_lines(help_text, help_width)
      File "/home/zbyszek/python/cpython/Lib/argparse.py", line 615, in _split_lines
        return _textwrap.wrap(text, width)
      File "/home/zbyszek/python/cpython/Lib/textwrap.py", line 316, in wrap
        return w.wrap(text)
      File "/home/zbyszek/python/cpython/Lib/textwrap.py", line 291, in wrap
        return self._wrap_chunks(chunks)
      File "/home/zbyszek/python/cpython/Lib/textwrap.py", line 220, in _wrap_chunks
        raise ValueError("invalid width %r (must be > 0)" % self.width)
    ValueError: invalid width -1 (must be > 0)

    argparse should not fail if the user resizes the window to something very thin...

    @zbysz zbysz mannequin added the stdlib Python modules in the Lib dir label Jan 6, 2012
    @terryjreedy
    Copy link
    Member

    The code works fine on 3.2.2, Win7, IDLE, narrowest window possible (about 14 chars), which actually wraps to the window width. (In command window, lines are fixed length and scroll bar is added if window is narrowed.) What system and version are you running?

    The error directly comes from textwrap. In the other hand, textwrap.wrap works with widths down to 1 (on 3.2.2), which suggests that argparse is calling it wrong. Except that it is not on my system.

    Could you add 'print(width)' before the call to textwrap
    return _textwrap.wrap(text, width)
    to see if -1 is being passed?

    @zbysz
    Copy link
    Mannequin Author

    zbysz mannequin commented Jan 7, 2012

    What system and version are you running?
    Linux (debian amd64), Python is compiled from hg (1ea8b7233fd7).

    The error directly comes from textwrap. In the other hand,
    textwrap.wrap works with widths down to 1 (on 3.2.2), which suggests
    that argparse is calling it wrong. Except that it is not on my system.
    That's really surprising, because it is all pure Python code and don't
    really see how it _could_ be right: take $COLUMNS, subtract, subtract,
    and sooner or later _width will go below 0.

    Could you add 'print(width)' before the call to textwrap
    return _textwrap.wrap(text, width)
    to see if -1 is being passed?
    Prints -1.

    The code works fine on 3.2.2, Win7, IDLE, narrowest window possible (about 14
    chars), which actually wraps to the window width.
    Oh, I just tried it in IDLE and it prints:
    64
    64
    64
    64
    usage: ...
    in a very small window (30 cells wide). So IDLE is just doesn't allow you to
    go below a certain size.

    See also bpo-13107.

    @terryjreedy
    Copy link
    Member

    I am not setting columns, so that might be the important difference.

    @zbysz
    Copy link
    Mannequin Author

    zbysz mannequin commented Jan 7, 2012

    I am not setting columns, so that might be the important difference.
    Yeah, the whole example with IDLE is moot: argparse only checks
    $COLUMNS and defaults to 80, so if COLUMNS is not set, you are only
    checking if the code works with 80 columns.

    Please try my commandline example or set os.environ['COLUMNS'] = 15.
    I get the exception in IDLE too.

    @terryjreedy
    Copy link
    Member

    Now I get error, even with Window actually about 100 columns wide.

    @RussellSim
    Copy link
    Mannequin

    RussellSim mannequin commented Jul 22, 2012

    Hi,

    I am having the same problem while running ipython in a batch mode emacs. Apparently you can't even start ipython if the columns are less than 27, since they use the argparse library for the magic method help printing and they preformat the strings at import time. So importing the library fails. :(

    I have a simple patch that fixes it but from what i can tell if you set the columns to 10 or 1000 there is no effect on the output, so i wonder if it even pays any attention to the width during rendering.

    If you think it's of value I am happy to write tests. Or if someone has a better implementation idea I'll be happy to implement it, but if you are on a terminal that is getting <27 characters then you can't really expect the formmating of the messages to be that readable.

    --- cpython/Lib/argparse.py	2012-07-22 12:10:42.751869655 +1000
    +++ /tmp/ediff3953qkY	2012-07-22 12:54:51.380700044 +1000
    @@ -95,6 +95,7 @@
     def _callable(obj):
         return hasattr(obj, '__call__') or hasattr(obj, '__bases__')
     
    +MIN_WIDTH = 10
     
     SUPPRESS = '==SUPPRESS=='
     
    @@ -486,7 +487,10 @@
             # determine the required width and the entry label
             help_position = min(self._action_max_length + 2,
                                 self._max_help_position)
    -        help_width = self._width - help_position
    +        if self._width - help_position > MIN_WIDTH:
    +            help_width = self._width - help_position
    +        else:
    +            help_width = MIN_WIDTH
             action_width = help_position - self._current_indent - 2
             action_header = self._format_action_invocation(action)

    @bethard
    Copy link
    Mannequin

    bethard mannequin commented Jul 23, 2012

    Definitely a bug here. Attached is a patch and a test, based on Russell Sim's suggestion, that should fix it.

    @serhiy-storchaka
    Copy link
    Member

    Thank you Zbyszek and Steven for your report and patch, but this was fixed in bpo-13107.

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    stdlib Python modules in the Lib dir
    Projects
    None yet
    Development

    No branches or pull requests

    2 participants