pip: pip freeze returns "Permission denied: 'hg'" after using pip install -e

Environment

  • pip version: 19.3.1 and above
  • Python version: 3.7.7
  • OS: macOS 10.14.6

Description After using pip install -e to install a local package, pip freeze returns an error: PermissionError: [Errno 13] Permission denied: 'hg'.

I do not use Mercurial and do not have an hg executable on my machine.

It happens with pip 19.3.1 and above, when using -e.

It doesn’t happen with pip 19.2.3, and it doesn’t happen if I don’t use -e. It doesn’t happen with pip list.

Expected behavior pip freeze should return the list of packages.

How to Reproduce Create a simple package, install it using pip install -e, then run pip freeze. It works with pip 19.2.3 but in 19.3.1 or later versions, pip freeze returns an error.

You can just copy/paste the following, which creates a virtual environment and does the pip install -e and the pip freeze on two different versions of pip:

cd
mkdir testdir
cd testdir/
virtualenv testenv
source testenv/bin/activate
mkdir my_plugin
echo "
from setuptools import setup

setup(
    name='my_plugin',
    py_modules=['my_plugin'],
    version='1.0.0',
)
" > my_plugin/setup.py
pip install pip==19.2.3
pip -V
pip install -e my_plugin/
pip freeze
pip uninstall -y my_plugin
pip freeze
pip install pip==19.3.1
pip -V
pip install -e my_plugin/
pip freeze
pip uninstall -y my_plugin
pip freeze

Output Here’s the output of the above commands, starting at the first pip -V:

$ pip -V
pip 19.2.3 from /Users/<username>/testdir/testenv/lib/python3.7/site-packages/pip (python 3.7)
$ pip install -e my_plugin/
Obtaining file:///Users/<username>/testdir/my_plugin
Installing collected packages: my-plugin
  Running setup.py develop for my-plugin
Successfully installed my-plugin
WARNING: You are using pip version 19.2.3, however version 20.2b1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
$ pip freeze
# Editable install with no version control (my-plugin==1.0.0)
-e /Users/<username>/testdir/my_plugin
$ pip uninstall -y my_plugin
Uninstalling my-plugin-1.0.0:
  Successfully uninstalled my-plugin-1.0.0
$ pip freeze
$ pip install pip==19.3.1
Collecting pip==19.3.1
  Using cached https://files.pythonhosted.org/packages/00/b6/9cfa56b4081ad13874b0c6f96af8ce16cfbc1cb06bedf8e9164ce5551ec1/pip-19.3.1-py2.py3-none-any.whl
Installing collected packages: pip
  Found existing installation: pip 19.2.3
    Uninstalling pip-19.2.3:
      Successfully uninstalled pip-19.2.3
Successfully installed pip-19.3.1
$ pip -V
pip 19.3.1 from /Users/<username>/testdir/testenv/lib/python3.7/site-packages/pip (python 3.7)
$ pip install -e my_plugin/
Obtaining file:///Users/<username>/testdir/my_plugin
Installing collected packages: my-plugin
  Running setup.py develop for my-plugin
Successfully installed my-plugin
WARNING: You are using pip version 19.3.1; however, version 20.1.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
$ pip freeze
ERROR: Exception:
Traceback (most recent call last):
  File "/Users/<username>/testdir/testenv/lib/python3.7/site-packages/pip/_internal/cli/base_command.py", line 153, in _main
    status = self.run(options, args)
  File "/Users/<username>/testdir/testenv/lib/python3.7/site-packages/pip/_internal/commands/freeze.py", line 100, in run
    for line in freeze(**freeze_kwargs):
  File "/Users/<username>/testdir/testenv/lib/python3.7/site-packages/pip/_internal/operations/freeze.py", line 70, in freeze
    req = FrozenRequirement.from_dist(dist)
  File "/Users/<username>/testdir/testenv/lib/python3.7/site-packages/pip/_internal/operations/freeze.py", line 249, in from_dist
    req, editable, comments = get_requirement_info(dist)
  File "/Users/<username>/testdir/testenv/lib/python3.7/site-packages/pip/_internal/operations/freeze.py", line 188, in get_requirement_info
    vcs_backend = vcs.get_backend_for_dir(location)
  File "/Users/<username>/testdir/testenv/lib/python3.7/site-packages/pip/_internal/vcs/versioncontrol.py", line 234, in get_backend_for_dir
    if vcs_backend.controls_location(location):
  File "/Users/<username>/testdir/testenv/lib/python3.7/site-packages/pip/_internal/vcs/mercurial.py", line 149, in controls_location
    log_failed_cmd=False)
  File "/Users/<username>/testdir/testenv/lib/python3.7/site-packages/pip/_internal/vcs/versioncontrol.py", line 632, in run_command
    log_failed_cmd=log_failed_cmd)
  File "/Users/<username>/testdir/testenv/lib/python3.7/site-packages/pip/_internal/utils/subprocess.py", line 190, in call_subprocess
    stdout=subprocess.PIPE, cwd=cwd, env=env,
  File "/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/subprocess.py", line 800, in __init__
    restore_signals, start_new_session)
  File "/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/subprocess.py", line 1551, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
PermissionError: [Errno 13] Permission denied: 'hg'
$ pip uninstall -y my_plugin
Uninstalling my-plugin-1.0.0:
  Successfully uninstalled my-plugin-1.0.0
$ pip freeze
$ 

pip list still works. In fact, if I add pip list just before the problematic pip freeze in the chain of commands above, there is no error:

$ pip list
Package    Version
---------- -------
my-plugin  1.0.0  
pip        19.3.1 
setuptools 47.1.1 
wheel      0.34.2 
WARNING: You are using pip version 19.3.1; however, version 20.1.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
$ pip freeze
my-plugin==1.0.0

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 4
  • Comments: 20 (13 by maintainers)

Commits related to this issue

Most upvoted comments

It may make sense if we just treat PermissionError the same as FileNotFoundError in the version control code. The two exceptions both signal that the version control tool is not available, which is what we really care about, after all.

Another choice would be to perform our own command resolution logic (via shutil.which()) instead of relying the operating system to emit a FileNotFoundError for the subprocess. But I’m not quite sure if that’s feasible for pip right now (because Python 2).