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

Migrate tests to use pathlib.Path #11170

Merged
merged 2 commits into from
Jun 12, 2022
Merged

Migrate tests to use pathlib.Path #11170

merged 2 commits into from
Jun 12, 2022

Conversation

uranusjr
Copy link
Member

@uranusjr uranusjr commented Jun 7, 2022

I was annoyed enough to spend a day on this.

The pip-specific Path implementation has been removed, and all its usages replaced by pathlib.Path. The tmpdir and tmpdir_factory fixtures are also removed, and all usages replaced by tmp_path and tmp_path_factory, which use pathlib.Path.

As anyone might expect, the bulk of the work is simply adding str() everywhere.

@uranusjr uranusjr added the skip news Does not need a NEWS file entry (eg: trivial changes) label Jun 7, 2022
Copy link
Member

@pfmoore pfmoore left a comment

Choose a reason for hiding this comment

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

Generally I'm +1 on this. I'm going to assume that if the tests pass it's probably OK.

I did start reading through, and made a couple of comments, but I lost the will to live with all those str calls 🙂 Also, black reformattings make the diffs a bit harder to skim. I wouldn't bother doing it now1, but splitting the commit into (1) mechanical str changes, (2) black reformattings and (3) substantial changes, might hae made it easier to review.

I added a couple of suggestions, but they aren't critical - feel free to treat them as matters of opinion and stick with what you have.

Footnotes

  1. And to be 100% clear, if I'd been doing this PR I would never have thought of doing this either...

tests/functional/test_broken_stdout.py Outdated Show resolved Hide resolved
tests/functional/test_broken_stdout.py Outdated Show resolved Hide resolved
direct_url_path = get_created_direct_url_path(result, "testpkg")
assert direct_url_path
# patch direct_url.json to simulate an editable install
with open(direct_url_path) as f:
direct_url = DirectUrl.from_json(f.read())
direct_url = DirectUrl.from_json(direct_url_path.read_text())
Copy link
Member

Choose a reason for hiding this comment

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

Unrelated to the Path change, but shouldn't we specify an encoding here? (And below).

Copy link
Member Author

Choose a reason for hiding this comment

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

cc @sbidoul I’m not sure if platform-dependant encoding is intended here.

Copy link
Member

Choose a reason for hiding this comment

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

It is was not intended, no. I'll do a PR to fix this (it should not matter much for the tests in practice but I spotted one place in the code where it could be an issue).

@uranusjr uranusjr force-pushed the pathlib branch 27 times, most recently from eaa2503 to 1b0e0be Compare June 8, 2022 00:32
@uranusjr uranusjr force-pushed the pathlib branch 12 times, most recently from cf2047e to 5799151 Compare June 8, 2022 08:54
@pradyunsg
Copy link
Member

Hurray! Thanks for picking this up @uranusjr! ^.^

@uranusjr uranusjr force-pushed the pathlib branch 3 times, most recently from 04941e1 to eb75460 Compare June 8, 2022 10:53
The pip-specific Path implementation has been removed, and all its
usages replaced by pathlib.Path. The tmpdir and tmpdir_factory fixtures
are also removed, and all usages are replaced by tmp_path and
tmp_path_factory, which use pathlib.Path.

The pip() function now also accepts pathlib.Path so we don't need to put
str() everywhere. Path arguments are coerced with os.fspath() into str.
@uranusjr
Copy link
Member Author

uranusjr commented Jun 9, 2022

Hmm, a couple of failing tests that I can’t figure out. They pass on my machine, and this PR doesn’t even touch those.

FAILED tests/functional/test_freeze.py::test_freeze_with_pip
FAILED tests/functional/test_freeze.py::test_freeze_multiple_exclude_with_all

@sbidoul
Copy link
Member

sbidoul commented Jun 11, 2022

@uranusjr I can reproduce on Linux with nox -s test-3.8 -- -k test_freeze_multiple_exclude_with_all. It passes with test-3.7, however.

With 3.7, the pip freeze --all output is

# Editable install with no version control (coverage==6.4.1)
-e /tmp/pytest-of-me/pytest-0/coverage0/install
# Editable install with no version control (pip==22.2.dev0)
-e /tmp/pytest-of-me/pytest-0/pip0/pip/src
# Editable install with no version control (setuptools==62.3.3)
-e /tmp/pytest-of-me/pytest-0/setuptools0/install
# Editable install with no version control (wheel==0.37.1)
-e /tmp/pytest-of-me/pytest-0/wheel0/install

so there is pip== in it, albeit in the comment that says there is no vcs directory.

With 3.8 the pip freeze output is similar to what we have in the CI log

# Editable install with no version control (coverage==6.4.1)
-e /tmp/pytest-of-me/pytest-0/coverage0/install
-e git+ssh://git@github.com/sbidoul/pip@42359a9605d56a37ac9a1ca76ea08a3b01d48468#egg=pip
# Editable install with no version control (setuptools==62.3.3)
-e /tmp/pytest-of-me/pytest-0/setuptools0/install
# Editable install with no version control (wheel==0.37.1)
-e /tmp/pytest-of-me/pytest-0/wheel0/install

so here we have no pip== in the output because the pip install was detected as an editable with VCS.

That is super weird. Would the shutil.copytree in virtualenv_template behave differently across version and due to a change in this PR ?

We could fix the test with assert "pip==" in result.stdout or "#egg=pip" in result.stdout, which would make it more robust. Although understanding the root cause would be more satisfying.

@uranusjr
Copy link
Member Author

Ah interesting. So in a sense the test is wrong—the behaviour they intend to test was broken by #5031 (before it pip freeze would have outputted pip==22.2.dev0 instead of the editable location), but since the PR (accidentally?) put a pip== in the message, the test continued to pass.

I suspect the behaviour change is due to Path.resolve(). The pathlib implementation on this is known to vary ever so slightly from version to version (under the “bugfix” category), and our old str-based implementation used the naive abspath. I’ll investigate more deeply.

@uranusjr
Copy link
Member Author

uranusjr commented Jun 12, 2022

Found the exact bugfix that changed behaviour: python/cpython#83571

This can be fixed by using samefile instead of ==. Don’t use == for “does this path point to this thing” logic, folks.

This resolves a behavioral different between Python 3.7 and 3.8+, where
a == comparison would incorrectly compare Path against str and cause
incorrect results.
@uranusjr uranusjr marked this pull request as ready for review June 12, 2022 05:06
Copy link
Member

@sbidoul sbidoul left a comment

Choose a reason for hiding this comment

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

Thanks for doing this!

@uranusjr uranusjr merged commit ba11a20 into pypa:main Jun 12, 2022
@uranusjr uranusjr deleted the pathlib branch June 12, 2022 15:34
@pradyunsg
Copy link
Member

🎉

@@ -171,7 +170,7 @@ def _customize_site(self) -> None:
def clear(self) -> None:
self._create(clear=True)

def move(self, location: str) -> None:
def move(self, location: Union[Path, str]) -> None:
Copy link
Contributor

Choose a reason for hiding this comment

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

error: Argument 1 to "move" has incompatible type "Path"; expected "str"
see: https://github.com/python/typeshed/blob/91d6383d9d1ca38157ce46bb498a11347658db1d/stdlib/shutil.pyi#L105

Copy link
Member Author

Choose a reason for hiding this comment

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

So it seems PathLike support here was only added in 3.9, and pre-commit missed this since we only run linters against the newest Python version.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 7, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
skip news Does not need a NEWS file entry (eg: trivial changes)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants