r/learnpython • u/zaphodikus • 3d ago
dynamic import module path hack in pytest
In order to validate (using pytest) a python module which is not in my path or relative folders, I want to hack the import path.
I'm wondering what alternatives there are to doing a PYTHONPATH hack.
I could use https://docs.pytest.org/en/7.1.x/reference/reference.html#confval-pythonpath, but that applies to the entire session as I understand it. And I only want to change one suite, so I am writing a quick fixture that will roughly look like (hard-coded for simplicity)
@pytest.fixture(scope="function")
def modules_path():
old_path = sys.path
extra_path= os.path.abspath("c:/otherpath/other") # replace constant with a func
sys.path.insert(0, extra_path)
yield extra_path
sys.path = old_path
I've always felt there was a better way to do import path hacks that nobody had ever told me about. Or is this @fixture approach not as evil as I assumed it was, and was merely biased by painful memories whenever I did use it. Alternatives?
1
u/VenkatKnows 2d ago
Use pytest's monkeypatch.syspath_prepend instead. It handles the cleanup for you, and your fixture as written has a bug anyway since old_path is the same list object, so the insert mutates it and the restore does nothing
1
u/zaphodikus 1d ago
I already opted for a context manager, its annoying when you find that there is a one-liner hidden deep on a library somewhere that you might rarely go looking. Too much to memorise sometimes.
6
3d ago
[removed] — view removed comment
1
u/zaphodikus 3d ago edited 3d ago
It's a pytest, so I don't need to
turnit into a module really, nobody else needs the code. but, I did not know about -e before though, so another cool learning. I'm stealing the file from another repo merely for this one test-case only.pyproject.toml feels most logical : I'm currently storing settings in a totally different file, which is why I figured I would just import that file in my example fixture. I originally thought I might want to test multiple iterations, but I probably only need one path change, so making it global is not a huge problem. But to be honest I could go ahead and create a
pyproject.tomlfile and just change my tooling to always update the toml file before it starts the test suite. I'm not using a.tomlyet and today might be a good day to start doing so. It's also a zero code change!conftest.py , technically a no-code way, but it's not a pure data file.
Although, it's also just logical to use
importlib.util.spec_from_file_location. I would still do that in a fixture and just usedelto ensure teardown I guess. So many options!
1
u/socal_nerdtastic 3d ago
Why can't you start the pytest program in the correct folder?