Merge pull request #1254 from volatilityfoundation/issues/plugin-requirement-recursion

Core: Verify plugin requirements of plugins
This commit is contained in:
ikelos
2024-09-10 23:26:27 +01:00
committed by GitHub
@@ -527,12 +527,14 @@ class VersionRequirement(interfaces.configuration.RequirementInterface):
def __init__(
self,
name: str,
description: str = None,
description: Optional[str] = None,
default: bool = False,
optional: bool = False,
component: Type[interfaces.configuration.VersionableInterface] = None,
version: Optional[Tuple[int, ...]] = None,
) -> None:
if description is None:
description = f"Version {'.'.join([str(x) for x in version])} dependency on {component.__module__}.{component.__name__} unmet"
super().__init__(
name=name, description=description, default=default, optional=optional
)
@@ -544,15 +546,51 @@ class VersionRequirement(interfaces.configuration.RequirementInterface):
self._version = version
def unsatisfied(
self, context: interfaces.context.ContextInterface, config_path: str
self,
context: interfaces.context.ContextInterface,
config_path: str,
accumulator: Optional[
List[interfaces.configuration.VersionableInterface]
] = None,
) -> Dict[str, interfaces.configuration.RequirementInterface]:
# Mypy doesn't appreciate our classproperty implementation, self._plugin.version has no type
config_path = interfaces.configuration.path_join(config_path, self.name)
if not self.matches_required(self._version, self._component.version):
return {config_path: self}
recurse = True
if accumulator is None:
accumulator = set([self._component])
else:
if self._component in accumulator:
recurse = False
else:
accumulator.add(self._component)
# Check for child requirements
if (
issubclass(self._component, interfaces.configuration.ConfigurableInterface)
and recurse
):
result = {}
for requirement in self._component.get_requirements():
if not requirement.optional and isinstance(
requirement, VersionRequirement
):
result.update(
requirement.unsatisfied(
context, config_path, accumulator.copy()
)
)
if result:
result.update({config_path: self})
return result
context.config[interfaces.configuration.path_join(config_path, self.name)] = (
True
)
return {}
@classmethod