Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 615b54b

Browse files
committedNov 8, 2024·
Remove plugin types, register individual hooks instead
Signed-off-by: Facundo Tuesca <facundo.tuesca@trailofbits.com>
1 parent 9279db4 commit 615b54b

File tree

2 files changed

+42
-34
lines changed

2 files changed

+42
-34
lines changed
 

‎src/pip/_internal/models/plugin.py

+40-28
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@
66

77
logger = logging.getLogger(__name__)
88

9-
PLUGIN_TYPE_DIST_INSPECTOR = "dist-inspector"
10-
SUPPORTED_PLUGIN_TYPES = [PLUGIN_TYPE_DIST_INSPECTOR]
9+
PLUGIN_HOOK_PRE_DOWNLOAD = "pre_download"
10+
PLUGIN_HOOK_PRE_EXTRACT = "pre_extract"
11+
SUPPORTED_PLUGIN_HOOKS = [PLUGIN_HOOK_PRE_DOWNLOAD, PLUGIN_HOOK_PRE_EXTRACT]
1112

1213

1314
class Plugin(metaclass=abc.ABCMeta):
1415
@abc.abstractmethod
15-
def plugin_type(self) -> str:
16+
def provided_hooks(self) -> list[str]:
1617
raise NotImplementedError
1718

1819
@property
@@ -21,22 +22,40 @@ def name(self) -> str:
2122
raise NotImplementedError
2223

2324

24-
class DistInspectorPlugin(Plugin):
25+
class LoadedPlugin(Plugin):
2526
def __init__(self, name: str, loaded_module: ModuleType):
26-
assert loaded_module.plugin_type() == PLUGIN_TYPE_DIST_INSPECTOR
27-
if not hasattr(loaded_module, "pre_download") or not hasattr(
28-
loaded_module, "pre_extract"
29-
):
27+
self._pre_download = None
28+
self._pre_extract = None
29+
if not hasattr(loaded_module, "provided_hooks"):
3030
raise ValueError(
31-
f'Plugin "{name}" of type {PLUGIN_TYPE_DIST_INSPECTOR} is'
32-
"missing pre_download and/or pre_extract definitions"
31+
f"Ignoring plugin {name} due to missing provided_hooks definition"
3332
)
33+
for hook in loaded_module.provided_hooks():
34+
if hook == PLUGIN_HOOK_PRE_DOWNLOAD:
35+
if not hasattr(loaded_module, "pre_download"):
36+
raise ValueError(
37+
f'Plugin "{name}" wants to register a pre-download hook but '
38+
"does not define a pre_download method"
39+
)
40+
self._pre_download = loaded_module.pre_download
41+
elif hook == PLUGIN_HOOK_PRE_EXTRACT:
42+
if not hasattr(loaded_module, "pre_extract"):
43+
raise ValueError(
44+
f'Plugin "{name}" wants to register a pre-extract hook but '
45+
"does not define a pre_extract method"
46+
)
47+
self._pre_extract = loaded_module.pre_extract
48+
else:
49+
raise ValueError(
50+
f'Plugin "{name}" wants to register a hook of unknown type:'
51+
'"{hook}"'
52+
)
3453

3554
self._name = name
3655
self._module = loaded_module
3756

38-
def plugin_type(self) -> str:
39-
return self._module.plugin_type()
57+
def provided_hooks(self) -> list[str]:
58+
return self._module.provided_hooks()
4059

4160
@property
4261
def name(self) -> str:
@@ -46,26 +65,19 @@ def pre_download(self, url: str, filename: str, digest: str) -> None:
4665
# contract: `pre_download` raises `ValueError` to terminate
4766
# the operation that intends to download `filename` from `url`
4867
# with hash `digest`
49-
self._module.pre_download(url=url, filename=filename, digest=digest)
68+
if self._pre_download is not None:
69+
self._pre_download(url=url, filename=filename, digest=digest)
5070

5171
def pre_extract(self, dist: Path) -> None:
5272
# contract: `pre_extract` raises `ValueError` to terminate
5373
# the operation that intends to unarchive `dist`
54-
self._module.pre_extract(dist)
74+
if self._pre_extract is not None:
75+
self._module.pre_extract(dist)
5576

5677

57-
def plugin_from_module(name: str, loaded_module: ModuleType) -> Optional[Plugin]:
58-
if not hasattr(loaded_module, "plugin_type"):
59-
logger.warning("Ignoring plugin %s due to missing plugin_type definition", name)
60-
plugin_type = loaded_module.plugin_type()
61-
if plugin_type not in SUPPORTED_PLUGIN_TYPES:
62-
logger.warning(
63-
"Ignoring plugin %s due to unknown plugin type: %s", name, plugin_type
64-
)
65-
66-
if plugin_type == PLUGIN_TYPE_DIST_INSPECTOR:
67-
try:
68-
return DistInspectorPlugin(name, loaded_module)
69-
except ValueError as e:
70-
logger.warning("Ignoring plugin %s due to error: %s", name, e)
78+
def plugin_from_module(name: str, loaded_module: ModuleType) -> Optional[LoadedPlugin]:
79+
try:
80+
return LoadedPlugin(name, loaded_module)
81+
except ValueError as e:
82+
logger.warning("Ignoring plugin %s due to error: %s", name, e)
7183
return None

‎src/pip/_internal/utils/plugins.py

+2-6
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
from pathlib import Path
55
from typing import Iterator, List
66

7-
from pip._internal.models.plugin import DistInspectorPlugin, Plugin, plugin_from_module
7+
from pip._internal.models.plugin import LoadedPlugin, plugin_from_module
88

99
logger = logging.getLogger(__name__)
10-
_loaded_plugins: List[Plugin] = []
10+
_loaded_plugins: List[LoadedPlugin] = []
1111

1212

1313
def iter_entry_points(group_name: str) -> List[EntryPoint]:
@@ -64,8 +64,6 @@ def plugin_pre_download_hook(url: str, filename: str, digest: str) -> None:
6464
"""
6565

6666
for p in _loaded_plugins:
67-
if not isinstance(p, DistInspectorPlugin):
68-
continue
6967
with _only_raise_value_error(p.name):
7068
p.pre_download(url=url, filename=filename, digest=digest)
7169

@@ -82,7 +80,5 @@ def plugin_pre_extract_hook(dist: Path) -> None:
8280
"""
8381

8482
for p in _loaded_plugins:
85-
if not isinstance(p, DistInspectorPlugin):
86-
continue
8783
with _only_raise_value_error(p.name):
8884
p.pre_extract(dist)

0 commit comments

Comments
 (0)
Please sign in to comment.