Pipx: PyTest not in the environment?

I still try to become warm with the “new” pipx.
I have a minimal hello world repo illustrating the problem. I want to run unit tests using pytest and because of that pytest is defined as dependency in pyproject.toml.
But I am not sure if pytest is installed inside the virtual environment or if ti might be shadowed by the systems global pytest.

I installed my package via pipx install .. running pytest gives me the error that it can not import the module helloworldcli. But that module is what I have installed - I think so.

$ pytest
================================================ test session starts =================================================
platform linux -- Python 3.11.2, pytest-7.2.1, pluggy-1.0.0+repack
rootdir: /home/user/tech-demo-python-packaging/01a_terminal_helloworld_setuptools
collected 0 items / 1 error

======================================================= ERRORS =======================================================
________________________________________ ERROR collecting tests/test_dummy.py ________________________________________
ImportError while importing test module '/home/user/tech-demo-python-packaging/01a_terminal_helloworld_setuptools/tests/test_dummy.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/python3.11/importlib/__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
tests/test_dummy.py:7: in <module>
    import helloworldcli
E   ModuleNotFoundError: No module named 'helloworldcli'

But also this do not work:
python3 -c "import helloworldcli"
But shouldn’t it?

But the entry point helloworldterminal does work.

$ pipx list                           venvs are in /home/user/.local/pipx/venvs                                                                             apps are exposed on your $PATH at /home/user/.local/bin                                                                  package asciinema 2.4.0, installed using Python 3.11.2                                                                 - asciinema                                                                                                          package helloworld-cli 0.0.1, installed using Python 3.11.2                                                            - helloworldterminal                                                                 

I am totally confused.

To my knowledege pipx always creates a virtual environment. Right? So I need to install pytest also into that environment.
But the running pytest doesn’t find the package it should test. So I assume that the running pytest is not the one that was installed inside the environment. It must be the global pytest.

This is not a use case for pipx. Maybe what you want to do is possible, but that is not what it is made for.

1 Like

You have installed it into a virtual environment, and you are running pytest from the global environment, so this is expected.

Same here, python3 is Python from the global environment.

Generally speaking, you don’t want to run tests in a pipx-managed environment. Pipx is a tool to be used by your users to install your app, not by you to develop it.

Tools that manage project environments and run tasks like pytest include Hatch, PDM, tox, Rye and Poetry.

2 Likes

Consider this. If you have

# test_dummy.py
import pytest
import helloworldcli

Which environment should pytest come from?

1 Like

OK, then how do I “install” such a package as a developer to make pytest run on it?

Using poetry, tox, etc is not an option. Please keep it simple (not short but clear) as possible.
How is it intended that developers handle such situations?

Why? This is how most people do it. Tox in particular is wildly popular for that.

If you want to do it the manual way, that’s

python -m venv .venv
.venv/bin/pip install -e .
.venv/bin/pip install pytest
.venv/bin/pytest

but I really do encourage you to adopt one of these tools.

2 Likes

Right.

Sounds plausible. Did your check which one it is?

$ which pytest

Did you try running the one in the venv? I would guess it’s this:

$ /home/user/.local/pipx/venvs/bin/pytest

I don’t want to open the poetry-tox-otherfancytools-discussion. I am not experienced enough to have good and valuable arguments. But just saying it is “popular” is one of the most worst arguments especially in the Python world. There are a lot of “bad habits” around Python just because so many people doing it and newbie Python learners just adapting it without question it and without knowing what they are doing. They do not learn.

But my goal in context of this thread is to create a minimal as possible example about an hello world package with usable unit tests. The primary purpose is to have examples for my very old and complex “Back In Time” project which need to migrate from make-system to a python-build-system. And secondary the examples can also be a good tutorial for Python learners. I want to make it right, good and correct.

I want to make things obvious and explicit without hiding steps behind fancy tools.

Back to the topic…

“Whereis” tells me

$ whereis pytest
pytest: /usr/bin/pytest /home/user/.local/bin/pytest /usr/share/man/man1/pytest.1.gz

which is interesting because it misses the pipx installed pytest:

$ ls -l ~/.local/pipx/venvs/helloworld-cli/bin/pytest
-rwxr-xr-x 1 user user 259  7. Feb 09:01 /home/user/.local/pipx/venvs/helloworld-cli/bin/pytest*

OK, I call it explicit and also got the ModuleNotFoundError

$ ~/.local/pipx/venvs/helloworld-cli/bin/pytest -v
...
...ModuleNotFoundError...

I remembered another thing:

$ pipx run pytest
⚠️  pytest is already on your PATH and installed at /home/user/.local/bin/pytest. Downloading and running anyway.
...ModuleNotFoundError...

OK, am I right to say that “pipx” shouldn’t be used in such cases? It is invented for users not for developers?

As a developer I have to create the virtual environment myself (or using a helper tool like poetry) and dealing with that things?

OK, am I right to say that “pipx” shouldn’t be used in such cases? It is invented for users not for developers?

Isn’t this exactly what was already stated?

This is not a use case for pipx. Maybe what you want to do is possible, but that is not what it is made for.

Generally speaking, you don’t want to run tests in a pipx-managed environment. Pipx is a tool to be used by your users to install your app, not by you to develop it.

2 Likes

Yes, that is how I would do it. That is the most straightforward way. It will likely work with a whole range of projects. No intermediary tool to install beforehand (with potential bootstrapping issue).

3 Likes

I didn’t suggest these tools just because they’re popular, they’re good too :slight_smile:

You will find that Python packaging is not made of “one good, right, correct way” (though there are a number of deprecated wrong ways, like python setup.py install, etc.). The fragmentation of the ecosystem is a subject of recurring discussions, and so far an unsolved problem. Now, if you prefer the manual way, do it the manual way and be a happy man. I just want to say that using, say, Hatch, is not more or less “correct” than going the manual way with venv, in the same way as wget https://python.org is not more or less “correct” than curl -O https://python.org/index.html, or visiting https://python.org in your browser and saving the page source.

That pipx-installed pytest is in helloworld-cli’s environment. When pipx installs a tool, it creates a virtual environment for that tool and it basically symlinks the tool’s command(s) into ~/.local/bin/ (it’s not an actual symlink, because of Windows, but the idea is the same). Emphasis on: it symlinks the tool’s commands. Not any commands that happen to be installed in that virtual environment by dependencies. For example, if you do pipx install sphinx, you expect to be able to run sphinx-build. You don’t want this to also install pygmentize in your $PATH, just because Sphinx depends on Pygments and Pygments provides a pygmentize command.

That’s a bit more surprising, but I don’t know your exact setup (such as how you got pytest into that virtual environment in the first place).

What this does is: make a temporary virtual environment, install pytest into it, and run that pytest from that virtual environment – so, without access to your package, which is in a different virtual environment.

Yes.

Yes.

Yes.

3 Likes

Yes, it is. I just tried to paraphrase it because I am stubborn. :wink:

Thanks in advance for all your help. I appreciate that. It is really a value having so much professionals around giving insights into their workflow.
I really learn a lot from you.

FWIW, I do this, even though I installed Poetry (I might get rid of it, actually).

1 Like

But just saying it is “popular” is one of the most worst arguments especially in the Python world. There are a lot of “bad habits” around Python just because so many people doing it and newbie Python learners just adapting it without question it and without knowing what they are doing. They do not learn.

Then don’t learn from them. :slight_smile: There are a lot of bad habits in most languages. Python is one of the few languages that has a “pythonic” concept. I’d suggest in general to strive towards discovering and applying pythonic principles.

I want to make things obvious and explicit without hiding steps behind fancy tools.

I agree with the concept, but in practice you are using pipx (a “fancy tool”) that some have already mentioned isn’t the right tool in this case.

OK, am I right to say that “pipx” shouldn’t be used in such cases?

As you likely know, pipx works great when you want to run apps quickly in separate environments. You can potentially “inject” packages into existing environments, but pipx is not normally something you’d use to develop projects. You can certainly try to push what pipx can do. I have in the past, but it has limitations.

1 Like