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

Improve presentation of errors from subprocesses, during installation #10795

Merged
merged 17 commits into from
Jan 27, 2022

Conversation

pradyunsg
Copy link
Member

@pradyunsg pradyunsg commented Jan 14, 2022

Toward #10421

Before:

Screenshot 2022-01-14 at 11 09 16

After this PR:

Screenshot 2022-01-14 at 10 25 51

@pradyunsg pradyunsg changed the title Improve errors from subprocesses, during installation Improve presentation of errors from subprocesses, during installation Jan 14, 2022
@pradyunsg pradyunsg added this to the 22.0 milestone Jan 14, 2022
@pfmoore
Copy link
Member

pfmoore commented Jan 14, 2022

The new version looks amazing! No time for a review right now, but purely based on the usability of the new version, I approve 🙂

@pradyunsg
Copy link
Member Author

pradyunsg commented Jan 14, 2022

There is one major difference (you know, other than all the aesthetic improvements) -- there's a lot more lines in the output, on failures with --verbose. This is mostly because:

  • I changed out setuptools shim to be multi-line, instead of the semi-colon-heavy single line, which adds quite a few lines to the output.
  • I stopped printing the command line in regular non-verbose mode, but do print the full command when running in verbose mode. I have no clue why pip prints the full command in non-verbose mode but not the verbose mode. :)

Screenshot 2022-01-14 at 11 12 39

Screenshot 2022-01-14 at 11 06 49

@pradyunsg pradyunsg added C: error messages Improving error messages type: enhancement Improvements to functionality labels Jan 14, 2022
@pradyunsg
Copy link
Member Author

Okay, the unit test failures are string mismatches, as far as I can tell. I'll fix those in a bit.

This is ready for cloning and playing around with it, so... I'd appreciate feedback on this. You'll get a proverbial cookie if you're able to make the pretty error formatting logic fail with an exception. ^>^

Barring any showstopper concerns, I'd like to get this out in 22.0. Last I checked, the release manager is very excited about this change. ;)

@pradyunsg
Copy link
Member Author

pradyunsg commented Jan 15, 2022

OK, I'm gonna need some help figuring out what exactly the Windows failure is. You should be able to attach a debugger on the failing test, since this is a failure happening in-process.

@sbidoul
Copy link
Member

sbidoul commented Jan 16, 2022

Hi @pradyunsg this is a great improvement !

I made a couple of tests with metadata preparation and build errors. Works fine.

Looking at your screenshots above I was reminded that it is weird that it prints "Preparing metadata (setup.py)... error" after the error in verbose mode, and before in non verbose mode. The former is a bit weird, but it was like that before and is probably a side effect of the absence of the spinner. So that can be left for future improvements.

👍

@pradyunsg
Copy link
Member Author

I got myself a clean Windows VM, and I still can't reproduce the CI failure -- the test passes in that VM. >.<

@DiddiLeija
Copy link
Member

Hmm... let me try it on my Windows computer ;)

@notatallshaw
Copy link
Member

notatallshaw commented Jan 21, 2022

I can reproduce the failure, I actually get 5 failures compared to main, including the 1 in the CI, not sure if that makes this less helpful but here are my steps:

  1. Installed fresh Python 3.7.9
  2. Created virtual environment: py -3.7 -m venv .venv
  3. Activated virtual environment: .\.venv\Scripts\activate
  4. Installed test requirements: python -m pip install nox 'virtualenv<20'
  5. Cloned repo: git clone https://github.com/pradyunsg/pip
  6. Entered repo: cd pip
  7. Switched branch: git switch better-subprocess-errors
  8. Ran tests: nox -s test-3.7 -- -m unit --verbose --numprocesses auto --showlocals

Got 5 errors compared to main:

FAILED tests/unit/test_req.py::TestRequirementSet::test_environment_marker_extras - pip._internal.exceptions.MetadataGenerationFailed: metadata generation failed
FAILED tests/unit/resolution_resolvelib/test_requirement.py::test_new_resolver_requirement_has_name - pip._internal.exceptions.MetadataGenerationFailed: metadata generation failed
FAILED tests/unit/resolution_resolvelib/test_requirement.py::test_new_resolver_correct_number_of_matches - assert 0 == 3
FAILED tests/unit/resolution_resolvelib/test_requirement.py::test_new_resolver_candidates_match_requirement - pip._internal.exceptions.MetadataGenerationFailed: metadata generation failed
FAILED tests/unit/test_req.py::TestRequirementSet::test_unhashed_deps_on_require_hashes - pip._internal.exceptions.MetadataGenerationFailed: metadata generation failed

Main currently passes for me (as long as I switch to UTC, filed issue for that #10816)

@DiddiLeija
Copy link
Member

I tested with WIndows 10, Python 3.9.

Ran nox -s test-3.9 -- -m unit --verbose --numprocesses auto --showlocals and got the following 11 failures:

FAILED tests/unit/test_base_command.py::test_log_command_error - assert False
FAILED tests/unit/test_logging.py::TestIndentingFormatter::test_format_with_timestamp[INFO-2019-01-17T06:00:37,040 hello\n2019-01-17T06:00:37,040 world]
FAILED tests/unit/test_logging.py::TestIndentingFormatter::test_format_with_timestamp[WARNING-2019-01-17T06:00:37,040 WARNING: hello\n2019-01-17T06:00:37,040 world]
FAILED tests/unit/test_req_file.py::TestProcessLine::test_absolute_local_nested_req_files - pip._internal.exceptions....
FAILED tests/unit/test_req.py::TestRequirementSet::test_environment_marker_extras - pip._internal.exceptions.Metadata...
FAILED tests/unit/test_req.py::TestRequirementSet::test_unhashed_deps_on_require_hashes - pip._internal.exceptions.Me...
FAILED tests/unit/resolution_resolvelib/test_requirement.py::test_new_resolver_requirement_has_name - pip._internal.e...
FAILED tests/unit/resolution_resolvelib/test_requirement.py::test_new_resolver_correct_number_of_matches - assert 0 == 3
FAILED tests/unit/resolution_resolvelib/test_requirement.py::test_new_resolver_candidates_match_requirement - pip._in...

Some of them came from the issue that @notatallshaw pointed in #10816.

I would like to note that Pytest catched some "stderr outputs", that are just what this PR wanted to do:

------------------------------------------------ Captured stderr call -------------------------------------------------
  error: subprocess-exited-with-error

  × python setup.py egg_info did not run successfully.
  │ exit code: 1
  ╰─> [6 lines of output]
      Traceback (most recent call last):
        File "<string>", line 2, in <module>
        File "<pip-setuptools-caller>", line 23
          __file__ = 'C:\Users\Diego Ramirez\AppData\Local\Temp\pip-temp-rgc41rm6\simple_6b5e182fb1d648d7b07961f9bae809a8\setup.py'
                                                                                                                                   ^
      SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX escape
      [end of output]

  note: This error originates from a subprocess, and is likely not a problem with pip.

@pradyunsg
Copy link
Member Author

Does that test also fail on main for you?

@DiddiLeija
Copy link
Member

Which one?

@pradyunsg
Copy link
Member Author

test_unhashed_deps_on_require_hashes

@DiddiLeija
Copy link
Member

Ok. Seems like it doesn't fail:

FAILED tests/unit/test_base_command.py::test_log_file_command_error - assert False
FAILED tests/unit/test_base_command.py::test_log_command_success - AssertionError: assert '2019-01-17T00:00:37,040 fa...
FAILED tests/unit/test_base_command.py::test_log_command_error - assert False
FAILED tests/unit/test_req_file.py::TestProcessLine::test_absolute_local_nested_req_files - pip._internal.exceptions....
FAILED tests/unit/test_logging.py::TestIndentingFormatter::test_format_with_timestamp[INFO-2019-01-17T06:00:37,040 hello\n2019-01-17T06:00:37,040 world]
FAILED tests/unit/test_logging.py::TestIndentingFormatter::test_format_with_timestamp[WARNING-2019-01-17T06:00:37,040 WARNING: hello\n2019-01-17T06:00:37,040 world]

@pradyunsg
Copy link
Member Author

__file__ = 'C:\Users\Diego Ramirez\AppData\Local\Temp\pip-temp-rgc41rm6\simple_6b5e182fb1d648d7b07961f9bae809a8\setup.py'

OH. Ok ok, Windows paths and escaping is the issue. 🤦🏽

@pradyunsg
Copy link
Member Author

Thanks for testing this and posting that output @DiddiLeija! ^>^

It would've taken me a lot longer to figure out what I'd done wrong, if you hadn't posted the output of the runs as you were able to reproduce. Thanks! ^>^

This serves as additional context that can be presented in error
messages.
Modernise the shim, to account for the Python 3.2+ support matrix.

This also presents clearer error messages on failures, the included
comment helps inform users about why this shim exists and the traceback
now explicitly mentions `<pip-setuptools-shim>` to make it clearer to
users that this shim exists.
This is more in line with the rest of our output presentation logic.
This file should be importable in all other modules, which means it
can't be importing any of those modules (to prevent an import loop).
These errors now more clearly note where the error occurred and what
component is at fault.
This more clearly states where the error came from, presents it in a
more approachable format with context provided for what this error is
related to.
These are more pleasing colours and, more importantly, a clearer
presentation style of the package vs the error.
I'd like to use this in screenshots, but the os.environ makes it a bit
tricky to do.
This helps ensure that they aren't improperly handled due to the newer
string-in-string design for the setuptools invocation script.
@pradyunsg
Copy link
Member Author

Hurray! It passes!

@DiddiLeija
Copy link
Member

I tested again. I only had 6 failures.

FAILED tests/unit/test_base_command.py::test_log_command_success - AssertionError: assert '2019-01-17T00:00:37,040 fa...
FAILED tests/unit/test_base_command.py::test_log_command_error - assert False
FAILED tests/unit/test_base_command.py::test_log_file_command_error - assert False
FAILED tests/unit/test_logging.py::TestIndentingFormatter::test_format_with_timestamp[INFO-2019-01-17T06:00:37,040 hello\n2019-01-17T06:00:37,040 world]
FAILED tests/unit/test_logging.py::TestIndentingFormatter::test_format_with_timestamp[WARNING-2019-01-17T06:00:37,040 WARNING: hello\n2019-01-17T06:00:37,040 world]
FAILED tests/unit/test_req_file.py::TestProcessLine::test_absolute_local_nested_req_files - pip._internal.exceptions....

But they are exactly the same failures than the main failures (see #10795 (comment)). So, the relevant tests are now passing!

@pradyunsg pradyunsg mentioned this pull request Jan 26, 2022
Copy link
Member

@DiddiLeija DiddiLeija left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this can be merged now :)

Copy link
Member

@jezdez jezdez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Droool.

@pradyunsg pradyunsg merged commit 1cda23b into pypa:main Jan 27, 2022
@pradyunsg pradyunsg deleted the better-subprocess-errors branch January 27, 2022 07:09
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 12, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
C: error messages Improving error messages type: enhancement Improvements to functionality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants