pipx: Installing local package fails

Describe the bug

pipx fails to install a local package.

How to reproduce

pipx install .
Cannot determine package name from spec '.'. Check package spec for errors.

pipx --version
0.15.1.3

Expected behavior

The package should be installed.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 2
  • Comments: 37 (24 by maintainers)

Most upvoted comments

(I never understood what those googly eyes mean.)

Another option is to invoke the Python interpreter in isolated mode to exclude the current working directory from the path.

https://github.com/pipxproject/pipx/blob/155cef9236aa0290578df7b46148f32c58bb5f6f/src/pipx/venv.py#L298

Replace "-m" with "-Im" above. This is not strictly equivalent to pip list because it also excludes user packages, but pipx operates on the system level.

The aforementioned pip issue will be fixed in the upcoming 20.1 (due today). We can revisit it soon. One way to help is to try this again with the new pip version and see if the issue resolves itself.

Another idea I had (which may or may not be a hack) would be if we notice ‘.’ as the install directory, to change our cwd to one level up and then modify the path to specify the original directory by relative name.

Ah, checking location does not help, because pip would still “prefer” the package in cwd after pip install ., so the installed package is still not inspectable. I’ll try raising this issue to pip and see if it’s fixable there (I suspect yes, since it is “fixed” in pip list but not python -m pip list).

This is due to a quirk in pip’s behavior. If you run pip list or pip freeze from a directory that is pip-installable, without actually installing the package, it will list it as installed. Maybe it’s intentional, or maybe it’s just because it gets put on Python’s current path. In any case, this causes pipx to not be able to identify the package name. Fortunately, there is an easy workaround.

Install the package from any other directory. For example, try going up to the parent directory, then running

pipx install ./mypackage

The shared pip is updated automatically, see #396. The pip update will land in at most a month, but GitHub does not have a timer feature to auto close this when that happens. I’ll just close this.

Alternatively, just upgrade pipx’s pip: ~/.local/pipx/shared/bin/pip install -U pip

pipx doesn’t use your system’s pip - is the pipx version of pip, 20.1? pipx upgrade-all will upgrade the shared-library pip to the latest version.

The problem I have with -I is it has too many implications (ignoring all PYTHON environment variables). This might be a good idea anyway, but is a breaking change significant enough that needs to be discussed through (and probably a long testing period).

I don’t know - I’m just a passer-by 😃

I take them to mean “interesting!” although that could just be me.

Isolated mode is very interesting, it has other good effects too. https://docs.python.org/3/using/cmdline.html#id2

-I

Run Python in isolated mode. This also implies -E and -s. In isolated mode sys.path contains neither the script’s directory nor the user’s site-packages directory. All PYTHON* environment variables are ignored, too. Further restrictions may be imposed to prevent the user from injecting malicious code.

New in version 3.4.

The -E option ignores all PYTHON* environment variables, which could allow us to stop cleaning them in util.py run commands possibly.

Since pip allows so many different installation types, getting package names is tricky, and implementations change over time. So instead of building parsing of setup.py and other files into pipx, pipx installs the package to a temporary virtual environment and compares the pip’s package list before and after the installation. pipx abstracts away all the details of “how to install and list packages” to pip, since ultimately that’s what does the installation anyway.

Because pip lists the package as installed before the installation, pipx does not detect any newly installed packages and hence cannot determine the package name.