Skip to content

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

Merged
bluetech merged 13 commits into
pytest-dev:mainfrom
okken:9114_pythonpath_setting
Oct 5, 2021
Merged

Add a pythonpath setting to allow paths to be added to sys.path.#9134
bluetech merged 13 commits into
pytest-dev:mainfrom
okken:9114_pythonpath_setting

Conversation

@okken

@okken okken commented Sep 29, 2021

Copy link
Copy Markdown
Contributor

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

Comment thread testing/test_pythonpath.py Outdated

@bluetech bluetech left a comment

Copy link
Copy Markdown
Member

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.

Comment thread src/_pytest/pythonpath.py Outdated
Comment thread src/_pytest/pythonpath.py
Comment thread src/_pytest/pythonpath.py Outdated
Comment thread src/_pytest/pythonpath.py Outdated
Comment thread src/_pytest/pythonpath.py Outdated
Comment thread src/_pytest/pythonpath.py Outdated
@okken

okken commented Sep 30, 2021

Copy link
Copy Markdown
Contributor Author

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?

Comment thread testing/test_pythonpath.py Outdated
@okken

okken commented Sep 30, 2021

Copy link
Copy Markdown
Contributor Author

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

@bluetech bluetech left a comment

Copy link
Copy Markdown
Member

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 :)

Comment thread src/_pytest/pythonpath.py Outdated
Comment thread src/_pytest/pythonpath.py Outdated
Comment thread testing/test_pythonpath.py Outdated
okken and others added 2 commits September 30, 2021 21:37
Comment thread src/_pytest/pythonpath.py Outdated
Comment thread src/_pytest/pythonpath.py Outdated
Comment thread src/_pytest/pythonpath.py Outdated
Comment thread src/_pytest/pythonpath.py Outdated
Comment thread src/_pytest/pythonpath.py Outdated

@bluetech bluetech left a comment

Copy link
Copy Markdown
Member

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.

Comment thread src/_pytest/pythonpath.py Outdated
Comment thread changelog/9114.feature.rst Outdated
@RonnyPfannschmidt

Copy link
Copy Markdown
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

okken commented Oct 1, 2021

Copy link
Copy Markdown
Contributor Author

@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

okken commented Oct 1, 2021

Copy link
Copy Markdown
Contributor Author

@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.

@bluetech bluetech left a comment

Copy link
Copy Markdown
Member

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.

Comment thread changelog/9114.feature.rst Outdated
Comment thread doc/en/reference/reference.rst Outdated
Comment thread doc/en/reference/reference.rst Outdated
Co-authored-by: Ran Benita <ran@unusedvar.com>
@okken

okken commented Oct 2, 2021

Copy link
Copy Markdown
Contributor Author

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

@okken

okken commented Oct 2, 2021

Copy link
Copy Markdown
Contributor Author

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

@bluetech bluetech left a comment

Copy link
Copy Markdown
Member

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.

Comment thread src/_pytest/config/__init__.py Outdated
@bluetech

bluetech commented Oct 3, 2021

Copy link
Copy Markdown
Member

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
Copy Markdown

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
Copy Markdown
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

@bluetech bluetech left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM!

@nicoddemus nicoddemus left a comment

Copy link
Copy Markdown
Member

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!

@RonnyPfannschmidt RonnyPfannschmidt left a comment

Copy link
Copy Markdown
Member

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

bluetech commented Oct 5, 2021

Copy link
Copy Markdown
Member

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
Copy Markdown

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
Copy Markdown
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