Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Impossible to unistall invalid package (with wrong entry point name) #2203

Closed
Conchylicultor opened this issue Jun 19, 2020 · 1 comment
Closed
Labels

Comments

@Conchylicultor
Copy link

Conchylicultor commented Jun 19, 2020

Edit: My issue is unrelated to Python2, but it doesn't looks like I can remove the label.

This issue was first posted in pypa/pip#8461 but PIP author redirected me instead. This may require change in both PIP and setuptools.

Environment

  • pip version: pip 20.1.1
  • Python version: 3.6
  • OS: MacOs

Description

I was experimenting with entry_points and released a test pip package with an invalid "entry-point" name: epot-test:

[tool.poetry.plugins."epot-test.test"]
"abc" = "epot_poetry_test.sub.other:SomeClass"

The pip install failed but pip is now in a bad state. Now it is impossible for me to uninstall the corrupted package.

Expected behavior
I would expect to be able to uninstall invalid packages.

How to Reproduce

pip install epot-poetry-test==0.2.0  # Install the corrupted package

# After the corrupted package is installed, it cannot be uninstalled or replaced:
pip uninstall epot-poetry-test  # Fail
pip epot-poetry-test --upgrade  # Fail

Output

epot-macbookpro% pip3 uninstall epot-poetry-test     
Found existing installation: epot-poetry-test 0.2.0
ERROR: Exception:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pip/_vendor/pkg_resources/__init__.py", line 2857, in get_entry_map
    ep_map = self._ep_map
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pip/_vendor/pkg_resources/__init__.py", line 2815, in __getattr__
    raise AttributeError(attr)
AttributeError: _ep_map

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pip/_internal/cli/base_command.py", line 188, in _main
    status = self.run(options, args)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pip/_internal/commands/uninstall.py", line 86, in run
    auto_confirm=options.yes, verbose=self.verbosity > 0,
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pip/_internal/req/req_install.py", line 675, in uninstall
    uninstalled_pathset = UninstallPathSet.from_dist(dist)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pip/_internal/req/req_uninstall.py", line 571, in from_dist
    console_scripts = dist.get_entry_map(group='console_scripts')
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pip/_vendor/pkg_resources/__init__.py", line 2860, in get_entry_map
    self._get_metadata('entry_points.txt'), self
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pip/_vendor/pkg_resources/__init__.py", line 2535, in parse_map
    maps[group] = cls.parse_group(group, lines, dist)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pip/_vendor/pkg_resources/__init__.py", line 2510, in parse_group
    raise ValueError("Invalid group name", group)
ValueError: ('Invalid group name', 'epot-test.test')

The only way I found was to manually found where the corrupted package was installed and remove the faulty entry point.

@jaraco
Copy link
Member

jaraco commented Jul 10, 2020

I was able to replicate the issue thus:

draft $ mkdir foo.dist-info                                                                                                                                
draft $ cat > foo.dist-info/entry_points.txt                                                                                                               
[foo-bar]
bang = baz
draft $ cat > foo.dist-info/METADATA                                                                                                                       
Name: foo
Version: 1.0
draft $ python -c "import pkg_resources; pkg_resources.get_entry_map('foo')"                                                                               
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pkg_resources/__init__.py", line 2864, in get_entry_map
    ep_map = self._ep_map
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pkg_resources/__init__.py", line 2822, in __getattr__
    raise AttributeError(attr)
AttributeError: _ep_map

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pkg_resources/__init__.py", line 495, in get_entry_map
    return get_distribution(dist).get_entry_map(group)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pkg_resources/__init__.py", line 2866, in get_entry_map
    ep_map = self._ep_map = EntryPoint.parse_map(
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pkg_resources/__init__.py", line 2542, in parse_map
    maps[group] = cls.parse_group(group, lines, dist)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pkg_resources/__init__.py", line 2517, in parse_group
    raise ValueError("Invalid group name", group)
ValueError: ('Invalid group name', 'foo-bar')

This behavior is by design and has been around for a very long time. If the package had been created by setuptools, it would not have been allowed to be built, but because it was built by Poetry, the invalid name was allowed. I recommend that Poetry disallow installation of these invalid names.

Since pkg_resources is discouraged for accessing entry points, I recommend that pip switch to importlib.metadata, which is more lenient around reading entry points:

draft $ python -c "import importlib.metadata as md; print(md.distribution('foo').entry_points)"                                                            
[EntryPoint(name='bang', value='baz', group='foo-bar')]

It's arguably an error that foo-bar is found there, but even if that's fixed, it's likely that the fix will be to warn about or omit the faulty name, and not crash with a ValueError as found in pkg_resources.

@jaraco jaraco closed this as completed Jul 10, 2020
@jaraco jaraco added the wontfix label Jul 10, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants