| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 |
- from __future__ import annotations
- import sys
- from collections import OrderedDict
- from importlib.metadata import entry_points
- from typing import TYPE_CHECKING
- if TYPE_CHECKING:
- from collections.abc import Sequence
- from python_discovery import PythonInfo
- from virtualenv.config.cli.parser import VirtualEnvConfigParser, VirtualEnvOptions
- importlib_metadata_version = ()
- class PluginLoader:
- _OPTIONS = None
- _ENTRY_POINTS = None
- @classmethod
- def entry_points_for(cls, key: str) -> OrderedDict[str, type]:
- if sys.version_info >= (3, 10) or importlib_metadata_version >= (3, 6):
- return OrderedDict((e.name, e.load()) for e in cls.entry_points().select(group=key)) # ty: ignore[unresolved-attribute]
- return OrderedDict((e.name, e.load()) for e in cls.entry_points().get(key, {})) # ty: ignore[unresolved-attribute]
- @staticmethod
- def entry_points() -> object:
- if PluginLoader._ENTRY_POINTS is None:
- PluginLoader._ENTRY_POINTS = entry_points()
- return PluginLoader._ENTRY_POINTS
- class ComponentBuilder(PluginLoader):
- def __init__(
- self, interpreter: PythonInfo, parser: VirtualEnvConfigParser, name: str, possible: dict[str, type]
- ) -> None:
- self.interpreter = interpreter
- self.name = name
- self._impl_class = None
- self.possible = possible
- self.parser = parser.add_argument_group(title=name)
- self.add_selector_arg_parse(name, list(self.possible))
- @classmethod
- def options(cls, key: str) -> OrderedDict[str, type]:
- if cls._OPTIONS is None:
- cls._OPTIONS = cls.entry_points_for(key)
- return cls._OPTIONS
- def add_selector_arg_parse(self, name: str, choices: Sequence[str]) -> None:
- raise NotImplementedError
- def handle_selected_arg_parse(self, options: VirtualEnvOptions) -> str:
- selected = getattr(options, self.name)
- if selected not in self.possible:
- msg = f"No implementation for {self.interpreter}"
- raise RuntimeError(msg)
- self._impl_class = self.possible[selected]
- self.populate_selected_argparse(selected, options.app_data)
- return selected
- def populate_selected_argparse(self, selected: str, app_data: object) -> None:
- self.parser.description = f"options for {self.name} {selected}"
- assert self._impl_class is not None # noqa: S101 # Set by handle_selected_arg_parse
- self._impl_class.add_parser_arguments(self.parser, self.interpreter, app_data) # ty: ignore[unresolved-attribute]
- def create(self, options: VirtualEnvOptions) -> object:
- assert self._impl_class is not None # noqa: S101 # Set by handle_selected_arg_parse
- return self._impl_class(options, self.interpreter)
- __all__ = [
- "ComponentBuilder",
- "PluginLoader",
- ]
|