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

Add a pythonpath setting to allow paths to be added to sys.path. #9134

Merged
merged 13 commits into from Oct 5, 2021

Conversation

okken
Copy link
Contributor

@okken okken commented Sep 29, 2021

Closes #9114
Closes #8964

I made a lot of assumptions here, so please comment if necessary.

  • implemented as a plugin in a new file.
  • test is in a new test file.
  • tests make sense to me, but if they are not clear, please let me know.
  • The changelog entry seems very terse, but I'm at a loss as to how to expand it, at the moment.

Question:

  • If this is accepted, I assume that docs will need modified. Is that usually part of the initial PR? or does that come later in the process?

Implementation is based on:

  • plugins pytest-pythonpath, pytest-srcpaths
  • comment from @bluetech in the issue thread regarding names, hook function to use, and reversing the order of path inclusion

Copy link
Member

@bluetech bluetech left a comment

Choose a reason for hiding this comment

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

Thanks @okken, looking good! I left some comments.

Also:


We need to document this feature somewhere.


I think the plugin can use a cleanup hook. While the vast majority of users use pytest thru the pytest command, where the the session only executes once and then the interpreter exits, it is also possible to use pytest.main(). Without cleanup, if someone calls pytest.main() then goes on to do other stuff, their sys.path will be polluted.

There are various approaches to doing the cleanup I can think of:

  1. Take a sys.path snapshot before, just restore it after.
  2. Remove the pythonpath values indiscriminately.
  3. Remove the pythonpath values if they match their expected positions.

1 and 3 are safer, but have a problem that if say some library imported by pytest modifies sys.path at import time, it will get lost (1) or not cleanup (3).

2 however can mess with pre-existing sys.path.

Not sure what is best, basically what we want is to remove what we added, and only that, maybe there's some trick to achieve it properly.

src/_pytest/pythonpath.py Outdated Show resolved Hide resolved
src/_pytest/pythonpath.py Show resolved Hide resolved
src/_pytest/pythonpath.py Outdated Show resolved Hide resolved
src/_pytest/pythonpath.py Outdated Show resolved Hide resolved
src/_pytest/pythonpath.py Outdated Show resolved Hide resolved
src/_pytest/pythonpath.py Outdated Show resolved Hide resolved
@okken
Copy link
Contributor Author

okken commented Sep 30, 2021

Pushed changes based on review feedback.
What's the process regarding "resolve conversation"? Should I click that on various comments when I agree? or when I've changed something? or just leave that button alone?

testing/test_pythonpath.py Outdated Show resolved Hide resolved
@okken
Copy link
Contributor Author

okken commented Sep 30, 2021

I've "resolved" some conversations after making changes. Let me know if that's NOT the correct procedure. :)

Copy link
Member

@bluetech bluetech left a comment

Choose a reason for hiding this comment

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

A couple more comments.

Feel free to resolve my comments as you fix them, the PR is small enough to keep everything in my head :)

src/_pytest/pythonpath.py Outdated Show resolved Hide resolved
src/_pytest/pythonpath.py Outdated Show resolved Hide resolved
testing/test_pythonpath.py Outdated Show resolved Hide resolved
okken and others added 2 commits September 30, 2021 21:37
src/_pytest/pythonpath.py Outdated Show resolved Hide resolved
src/_pytest/pythonpath.py Outdated Show resolved Hide resolved
src/_pytest/pythonpath.py Outdated Show resolved Hide resolved
src/_pytest/pythonpath.py Outdated Show resolved Hide resolved
Copy link
Member

@bluetech bluetech left a comment

Choose a reason for hiding this comment

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

The code looks good to me; nice and clean!

To verify, I tested it now on my aforementioned project which currently uses pytest-pythonpath. I found one issue, see line comments. With that fixed, it's working as intended.

As for the docs, just need to add a confval to doc/en/reference/reference.rst (and make the changelog entry reference it) and that would be enough as far as I'm concerned.

src/_pytest/pythonpath.py Outdated Show resolved Hide resolved
changelog/9114.feature.rst Outdated Show resolved Hide resolved
@RonnyPfannschmidt
Copy link
Member

@bluetech @okken would this be simplified if we provided config.exitstack as a exitstack that tears down contexts people add to it

then the actual iplementation would be a contextmanager thats unittestable + a configrue hook thats just putting it into the exit stack

@okken
Copy link
Contributor Author

okken commented Oct 1, 2021

@bluetech @RonnyPfannschmidt
Added a 1st draft of docs. Not sure how verbose to be. Should we mention application vs package testing, or leave that out?

@okken
Copy link
Contributor Author

okken commented Oct 1, 2021

@bluetech @RonnyPfannschmidt
Regarding exitstack, this isn't a complicated extension, so I don't think pythonpath requires it.
However, pythonpath plus many other builtin and external plugins could definitely benefit from some context manager based solution.
Really anywhere we have hook pairs. There may be more, but configure/unconfigure, sessionstart/sessionfinish, might find such a solution handy.
But at the very least, being able to use configure/unconfigure as a context manager would be cool. Especially if it kinda acted like fixture yield.
However, in the case of pythonpath, there really isn't that much extra work to re-look up the pythonpath values with getini.

Copy link
Member

@bluetech bluetech left a comment

Choose a reason for hiding this comment

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

Docs LGTM, with a few suggestions.

changelog/9114.feature.rst Outdated Show resolved Hide resolved
doc/en/reference/reference.rst Outdated Show resolved Hide resolved
doc/en/reference/reference.rst Outdated Show resolved Hide resolved
Co-authored-by: Ran Benita <ran@unusedvar.com>
@okken
Copy link
Contributor Author

okken commented Oct 2, 2021

Thanks @bluetech for the documentation assistance, as well as all the other help with this PR.

@okken
Copy link
Contributor Author

okken commented Oct 2, 2021

@bluetech Please let me know if there's anything else that needs done for this PR.

Copy link
Member

@bluetech bluetech left a comment

Choose a reason for hiding this comment

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

@bluetech Please let me know if there's anything else that needs done for this PR.

I took the liberty of adding a cleanup test and pushing it to your branch, PTAL and feel free to make any changes to it. With it, and the small suggestion below, it's good to go from my side.

Since it's a new feature, I'd like the other maintainers to approve as well. Particularly @nicoddemus -- this might have some interaction with the import modes which touch sys.path as well, though I think it should be OK.

src/_pytest/config/__init__.py Outdated Show resolved Hide resolved
@bluetech
Copy link
Member

bluetech commented Oct 3, 2021

Also cc the author of pytest-pythonpath, @ericpalakovichcarr: this PR adds the equivalent of pytest-pythonpath into pytest itself, as a core plugin. We'd love to hear if you have any thoughts or comments on this!

@ericpalakovichcarr
Copy link

Thanks for the heads up, @bluetech. Everything looks good to me. And hat tip to @okken getting this functionality into pytest 🎉

assert before is not None
assert after is not None
assert any("I_SHALL_BE_REMOVED" in entry for entry in before)
assert not any("I_SHALL_BE_REMOVED" in entry for entry in after)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Cool tests. Thanks @bluetech

Copy link
Member

@bluetech bluetech left a comment

Choose a reason for hiding this comment

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

LGTM!

Copy link
Member

@nicoddemus nicoddemus left a comment

Choose a reason for hiding this comment

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

Particularly @nicoddemus -- this might have some interaction with the import modes which touch sys.path as well, though I think it should be OK.

Thanks for the heads up. Indeed it is fine. 👍

Thanks @okken!

Copy link
Member

@RonnyPfannschmidt RonnyPfannschmidt left a comment

Choose a reason for hiding this comment

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

lovely, well done 👍

@bluetech bluetech merged commit c82bda2 into pytest-dev:main Oct 5, 2021
@bluetech
Copy link
Member

bluetech commented Oct 5, 2021

Thanks @okken!

hoefling pushed a commit to hoefling/pytest that referenced this pull request Oct 22, 2021
mweinelt added a commit to NixOS/nixpkgs that referenced this pull request Mar 9, 2022
Obsoleted by pytest-dev/pytest#9134, which was
released as part of pytest 7.0.0.

It has pytest<7 pinned, and we only have the single pytest version, so
it can be removed.
mweinelt added a commit to NixOS/nixpkgs that referenced this pull request Mar 10, 2022
Obsoleted by pytest-dev/pytest#9134, which was
released as part of pytest 7.0.0.

It has pytest<7 pinned, and we only have the single pytest version, so
it can be removed.
mweinelt added a commit to NixOS/nixpkgs that referenced this pull request Mar 12, 2022
Obsoleted by pytest-dev/pytest#9134, which was
released as part of pytest 7.0.0.

It has pytest<7 pinned, and we only have the single pytest version, so
it can be removed.
mweinelt added a commit to NixOS/nixpkgs that referenced this pull request Mar 13, 2022
Obsoleted by pytest-dev/pytest#9134, which was
released as part of pytest 7.0.0.

It has pytest<7 pinned, and we only have the single pytest version, so
it can be removed.
@LuminairPrime
Copy link

I was just going in circles for a while looking for this exact feature, lol! Everyone on the internet recommends pytest for Python testing, but nobody mentions how to actually get it working when your source and tests aren't next to each other. There are countless google hits for people suggesting "sys.path.append" code snippits. It's the wild west out there.

Maybe I should make a feature request for this. I think it would be good to add some mention in the basic documentation. For example, the files:
https://docs.pytest.org/en/7.1.x/getting-started.html
https://docs.pytest.org/en/7.1.x/explanation/goodpractices.html

When there's mention of 1) starting a new project, or 2) a project directory hierarchy, there should be mention of setting pythonpath in pyproject.toml to include your source path. It should be assumed that normies like me are reading this documentation and just want to get their first unit test on their first program to run.

@nicoddemus
Copy link
Member

Good point @LuminairPrime, created #9833 for this. Perhaps that's something you would like to contribute? 😁

bmwiedemann pushed a commit to bmwiedemann/openSUSE that referenced this pull request May 26, 2022
https://build.opensuse.org/request/show/972472
by user mcalabkova + dimstar_suse
from upstream README:
**NOTE:**  This plugin is obsolete as of pytest 7.0.0.  Thanks to [this PR](pytest-dev/pytest#9134) from [Brian Okken](https://github.com/okken), you can now modify the PYTHONPATH using the `pythonpath` configuration option.  See documentation here: https://docs.pytest.org/en/7.0.x/reference/reference.html#confval-pythonpath

... and as we didn't fork pytest 6, there is no package to provide pytest <7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add srcpaths setting How to make testing utilities importable when using importlib mode
6 participants