Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/pluggy/_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,14 @@ def unregister(
if self._name2plugin.get(name) is not None:
del self._name2plugin[name]

# Drop any entry-point bookkeeping for this plugin so that
# list_plugin_distinfo()/list_plugin_distributions() no longer report
# a plugin that has been unregistered (and re-registration through
# entry points does not leave a duplicate entry behind).
self._plugin_distinfo[:] = [
(p, dist) for p, dist in self._plugin_distinfo if p is not plugin
]

return plugin

def set_blocked(self, name: str) -> None:
Expand Down
43 changes: 43 additions & 0 deletions testing/test_pluginmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -960,6 +960,49 @@ def my_distributions():
assert ret_distributions == [(plugin, dist)]


def test_unregister_removes_plugin_distinfo(
monkeypatch: pytest.MonkeyPatch, pm: PluginManager
) -> None:
"""Unregistering drops entry-point bookkeeping (#763).

``list_plugin_distinfo()`` / ``list_plugin_distributions()`` must not
report a plugin after it has been unregistered, and re-registering
through entry points must not leave a duplicate entry behind.
"""

class EntryPoint:
name = "myname"
group = "hello"
value = "myname:foo"

def load(self):
class PseudoPlugin:
x = 42

return PseudoPlugin()

class Distribution:
entry_points = (EntryPoint(),)

dist = cast(importlib.metadata.Distribution, Distribution())

monkeypatch.setattr(importlib.metadata, "distributions", lambda: (dist,))

assert pm.load_setuptools_entrypoints("hello") == 1
assert len(pm.list_plugin_distinfo()) == 1
assert pm.list_plugin_distributions() == [(pm.get_plugin("myname"), dist)]

pm.unregister(name="myname")

assert pm.list_plugin_distinfo() == []
assert pm.list_plugin_distributions() == []

# Re-registering through entry points starts from a clean slate: exactly
# one entry, not a stale leftover plus a new one.
assert pm.load_setuptools_entrypoints("hello") == 1
assert len(pm.list_plugin_distributions()) == 1


def test_add_tracefuncs(he_pm: PluginManager) -> None:
out: list[Any] = []

Expand Down
Loading