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

Test failures with Python 3.13.0b2 #228

Closed
mgorny opened this issue Jun 13, 2024 · 3 comments
Closed

Test failures with Python 3.13.0b2 #228

mgorny opened this issue Jun 13, 2024 · 3 comments
Assignees
Labels
Milestone

Comments

@mgorny
Copy link

mgorny commented Jun 13, 2024

Summary

The test suite fails with Python 3.13.0b2. At a first glance, all the mismatches are because --help output changed. When a single argument has multiple option strings, argparse no longer repeats the placeholder, i.e. rather than -t TASK, --task TASK it gives -t, --task TASK.

To Reproduce

Command line input/output:

$ tox -e py313
.pkg: install_requires> python -I -m pip install 'flit_core<4,>=3.2'
.pkg: _optional_hooks> python /usr/lib/python3.12/site-packages/pyproject_api/_backend.py True flit_core.buildapi
.pkg: get_requires_for_build_sdist> python /usr/lib/python3.12/site-packages/pyproject_api/_backend.py True flit_core.buildapi
.pkg: build_sdist> python /usr/lib/python3.12/site-packages/pyproject_api/_backend.py True flit_core.buildapi
py313: install_package_deps> python -I -m pip install 'pytest-cov>=4.1' 'pytest>=7.4' 'tox>=4.11.3'
py313: install_package> python -I -m pip install --force-reinstall --no-deps /tmp/argh/.tox/.tmp/package/1/argh-0.31.2.tar.gz
py313: commands[0]> pytest --cov=argh --cov-report html --cov-fail-under 100 tests
========================================================= test session starts =========================================================
platform linux -- Python 3.13.0b2, pytest-8.2.2, pluggy-1.5.0
cachedir: .tox/py313/.pytest_cache
rootdir: /tmp/argh
configfile: pyproject.toml
plugins: cov-5.0.0
collected 169 items                                                                                                                   

tests/test_assembling.py ......................................                                                                 [ 22%]
tests/test_completion.py ...                                                                                                    [ 24%]
tests/test_decorators.py ......                                                                                                 [ 27%]
tests/test_dispatching.py ........                                                                                              [ 32%]
tests/test_dto.py ....                                                                                                          [ 34%]
tests/test_integration.py ........................................FF.....F..F.F..                                               [ 67%]
tests/test_interaction.py .....                                                                                                 [ 70%]
tests/test_mapping_policies.py ..........................                                                                       [ 85%]
tests/test_regressions.py ............                                                                                          [ 92%]
tests/test_typing_hints.py ........                                                                                             [ 97%]
tests/test_utils.py ....                                                                                                        [100%]

============================================================== FAILURES ===============================================================
___________________________________________________ test_default_arg_values_in_help ___________________________________________________

    def test_default_arg_values_in_help():
        "Argument defaults should appear in the help message implicitly"
    
        @argh.arg("name", default="Basil")
        @argh.arg("--task", default="hang the Moose")
        @argh.arg("--note", help="why is it a remarkable animal?")
        def remind(
            name,
            *,
            task=None,
            reason="there are creatures living in it",
            note="it can speak English",
        ):
            return "Oh what is it now, can't you leave me in peace..."
    
        parser = DebugArghParser()
        parser.set_default_command(remind)
    
        help_normalised = re.sub(r"\s+", " ", parser.format_help())
    
        assert "name 'Basil'" in help_normalised
>       assert "-t TASK, --task TASK 'hang the Moose'" in help_normalised
E       assert "-t TASK, --task TASK 'hang the Moose'" in "usage: pytest [-h] [-t TASK] [-r REASON] [-n NOTE] name positional arguments: name 'Basil' options: -h, --help show t...N 'there are creatures living in it' -n, --note NOTE why is it a remarkable animal? (default: 'it can speak English') "

tests/test_integration.py:727: AssertionError
_____________________________________________ test_default_arg_values_in_help__regression _____________________________________________

    def test_default_arg_values_in_help__regression():
        "Empty string as default value → empty help string → broken argparse"
    
        def foo(*, bar=""):
            return bar
    
        parser = DebugArghParser()
        parser.set_default_command(foo)
    
        # doesn't break
        parser.format_help()
    
        # now check details
>       assert "-b BAR, --bar BAR  ''" in parser.format_help()
E       assert "-b BAR, --bar BAR  ''" in "usage: pytest [-h] [-b BAR]\n\noptions:\n  -h, --help     show this help message and exit\n  -b, --bar BAR  ''\n"
E        +  where "usage: pytest [-h] [-b BAR]\n\noptions:\n  -h, --help     show this help message and exit\n  -b, --bar BAR  ''\n" = <bound method ArgumentParser.format_help of DebugArghParser(prog='pytest', usage=None, description=None, formatter_class=<class 'argh.constants.CustomFormatter'>, conflict_handler='error', add_help=True)>()
E        +    where <bound method ArgumentParser.format_help of DebugArghParser(prog='pytest', usage=None, description=None, formatter_class=<class 'argh.constants.CustomFormatter'>, conflict_handler='error', add_help=True)> = DebugArghParser(prog='pytest', usage=None, description=None, formatter_class=<class 'argh.constants.CustomFormatter'>, conflict_handler='error', add_help=True).format_help

tests/test_integration.py:754: AssertionError
___________________________________________________ test_add_commands_no_overrides2 ___________________________________________________

capsys = <_pytest.capture.CaptureFixture object at 0x7f319ffd4190>

    def test_add_commands_no_overrides2(capsys: pytest.CaptureFixture[str]):
        def first_func(*, foo=123):
            """Owl stretching time"""
    
        def second_func():
            pass
    
        parser = argh.ArghParser(prog="myapp")
        parser.add_commands([first_func, second_func])
    
        run(parser, "first-func --help", exit=True)
        captured = capsys.readouterr()
>       assert (
            captured.out
            == unindent(
                f"""
            usage: myapp first-func [-h] [-f FOO]
    
            Owl stretching time
    
            {HELP_OPTIONS_LABEL}:
              -h, --help         show this help message and exit
              -f FOO, --foo FOO  123
            """
            )[1:]
        )
E       AssertionError: assert 'usage: myapp...oo FOO  123\n' == 'usage: myapp...oo FOO  123\n'
E         
E         Skipping 76 identical leading characters in diff, use -v to show
E         - -help         show this help message and exit
E         ?           ----
E         + -help     show this help message and exit
E         -   -f FOO, --foo FOO  123
E         ?     ----
E         +   -f, --foo FOO  123

tests/test_integration.py:871: AssertionError
_________________________________________________ test_add_commands_group_overrides3 __________________________________________________

capsys = <_pytest.capture.CaptureFixture object at 0x7f31a0056210>

    def test_add_commands_group_overrides3(capsys: pytest.CaptureFixture[str]):
        """
        When `group_kwargs` is passed to `add_commands()`, its members override
        whatever was specified on function level.
        """
    
        def first_func(*, foo=123):
            """Owl stretching time"""
            return foo
    
        def second_func():
            pass
    
        parser = argh.ArghParser(prog="myapp")
        parser.add_commands(
            [first_func, second_func],
            group_name="my-group",
            group_kwargs={
                "help": "group help override",
                "description": "group description override",
            },
        )
    
        run(parser, "my-group first-func --help", exit=True)
        captured = capsys.readouterr()
>       assert (
            captured.out
            == unindent(
                f"""
            usage: myapp my-group first-func [-h] [-f FOO]
    
            Owl stretching time
    
            {HELP_OPTIONS_LABEL}:
              -h, --help         show this help message and exit
              -f FOO, --foo FOO  123
            """
            )[1:]
        )
E       AssertionError: assert 'usage: myapp...oo FOO  123\n' == 'usage: myapp...oo FOO  123\n'
E         
E         Skipping 85 identical leading characters in diff, use -v to show
E         - -help         show this help message and exit
E         ?           ----
E         + -help     show this help message and exit
E         -   -f FOO, --foo FOO  123
E         ?     ----
E         +   -f, --foo FOO  123

tests/test_integration.py:1000: AssertionError
__________________________________________________ test_add_commands_func_overrides2 __________________________________________________

capsys = <_pytest.capture.CaptureFixture object at 0x7f31a0013460>

    def test_add_commands_func_overrides2(capsys: pytest.CaptureFixture[str]):
        """
        When `func_kwargs` is passed to `add_commands()`, its members override
        whatever was specified on function level.
        """
    
        def first_func(*, foo=123):
            """Owl stretching time"""
            pass
    
        def second_func():
            pass
    
        parser = argh.ArghParser(prog="myapp")
        parser.add_commands(
            [first_func, second_func],
            func_kwargs={
                "help": "func help override",
                "description": "func description override",
            },
        )
    
        run(parser, "first-func --help", exit=True)
        captured = capsys.readouterr()
>       assert (
            captured.out
            == unindent(
                f"""
            usage: myapp first-func [-h] [-f FOO]
    
            func description override
    
            {HELP_OPTIONS_LABEL}:
              -h, --help         show this help message and exit
              -f FOO, --foo FOO  123
            """
            )[1:]
        )
E       AssertionError: assert 'usage: myapp...oo FOO  123\n' == 'usage: myapp...oo FOO  123\n'
E         
E         Skipping 82 identical leading characters in diff, use -v to show
E         - -help         show this help message and exit
E         ?           ----
E         + -help     show this help message and exit
E         -   -f FOO, --foo FOO  123
E         ?     ----
E         +   -f, --foo FOO  123

tests/test_integration.py:1082: AssertionError
========================================================== warnings summary ===========================================================
tests/test_dispatching.py::test_dispatch_command_two_stage
  /tmp/argh/src/argh/dispatching.py:167: DeprecationWarning: The argument `namespace` in `dispatch()` is deprecated. It will be removed in the next minor version after v0.31.
    warnings.warn(

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html

----------- coverage: platform linux, python 3.13.0-beta-2 -----------
Coverage HTML written to dir htmlcov

Required test coverage of 100% reached. Total coverage: 100.00%
======================================================= short test summary info =======================================================
FAILED tests/test_integration.py::test_default_arg_values_in_help - assert "-t TASK, --task TASK 'hang the Moose'" in "usage: pytest [-h] [-t TASK] [-r REASON] [-n NOTE] name positional arguments: n...
FAILED tests/test_integration.py::test_default_arg_values_in_help__regression - assert "-b BAR, --bar BAR  ''" in "usage: pytest [-h] [-b BAR]\n\noptions:\n  -h, --help     show this help message and exit\n  -b...
FAILED tests/test_integration.py::test_add_commands_no_overrides2 - AssertionError: assert 'usage: myapp...oo FOO  123\n' == 'usage: myapp...oo FOO  123\n'
FAILED tests/test_integration.py::test_add_commands_group_overrides3 - AssertionError: assert 'usage: myapp...oo FOO  123\n' == 'usage: myapp...oo FOO  123\n'
FAILED tests/test_integration.py::test_add_commands_func_overrides2 - AssertionError: assert 'usage: myapp...oo FOO  123\n' == 'usage: myapp...oo FOO  123\n'
============================================== 5 failed, 164 passed, 1 warning in 2.72s ===============================================
py313: exit 1 (3.22 seconds) /tmp/argh> pytest --cov=argh --cov-report html --cov-fail-under 100 tests pid=116532
.pkg: _exit> python /usr/lib/python3.12/site-packages/pyproject_api/_backend.py True flit_core.buildapi
  py313: FAIL code 1 (13.82=setup[10.60]+cmd[3.22] seconds)
  evaluation failed :( (13.95 seconds)

Expected behavior

Passing tests :-).

Environment

  • OS: Gentoo Linux amd64
  • Python version: 3.13.0b2
  • Argh version: 80f71e5

Additional context

n/a

@mgorny mgorny added the bug label Jun 13, 2024
@neithere neithere added this to the 0.31.3 milestone Jun 14, 2024
@neithere
Copy link
Owner

Thanks you for the report, @mgorny!

Looks like it's caused by this one: python/cpython#103372

Will update the tests.

@neithere
Copy link
Owner

Will be released with #225.

@mgorny
Copy link
Author

mgorny commented Jul 12, 2024

Thanks. I can confirm that the tests pass for with this commit applied.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants