mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-02-04 08:13:38 +00:00
package: Use package expressions in Packages component
- managed_packages() finds all possible packages that could be installed. This is used for the check in the action script. - resolve() finds actual packages to be installed. This is used in setup, diagnose, and has_unavailable_packages. Signed-off-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
parent
31a457029c
commit
45820fbdfa
@ -131,7 +131,7 @@ def _assert_managed_packages(module, packages):
|
||||
app = cls()
|
||||
components = app.get_components_of_type(Packages)
|
||||
for component in components:
|
||||
managed_packages += component.packages
|
||||
managed_packages += component.managed_packages()
|
||||
|
||||
for package in packages:
|
||||
assert package in managed_packages
|
||||
|
||||
@ -101,7 +101,8 @@ class Packages(app.FollowerComponent):
|
||||
IGNORE = 'ignore' # Proceed as if there are no conflicts
|
||||
REMOVE = 'remove' # Remove the packages before installing the app
|
||||
|
||||
def __init__(self, component_id: str, packages: list[str],
|
||||
def __init__(self, component_id: str,
|
||||
packages: list[Union[str, PackageExpression]],
|
||||
skip_recommends: bool = False,
|
||||
conflicts: Optional[list[str]] = None,
|
||||
conflicts_action: Optional[ConflictsAction] = None):
|
||||
@ -126,29 +127,50 @@ class Packages(app.FollowerComponent):
|
||||
super().__init__(component_id)
|
||||
|
||||
self.component_id = component_id
|
||||
self._packages = packages
|
||||
self._packages = []
|
||||
for package in packages:
|
||||
if isinstance(package, str):
|
||||
self._packages.append(Package(package))
|
||||
else:
|
||||
self._packages.append(package)
|
||||
|
||||
self.skip_recommends = skip_recommends
|
||||
self.conflicts = conflicts
|
||||
self.conflicts_action = conflicts_action
|
||||
|
||||
@property
|
||||
def packages(self) -> list[str]:
|
||||
"""Return the list of packages managed by this component."""
|
||||
def packages(self) -> list[Union[str, PackageExpression]]:
|
||||
"""Return the list of packages and package expressions managed by this
|
||||
component."""
|
||||
return self._packages
|
||||
|
||||
def managed_packages(self) -> list[str]:
|
||||
"""Return the list of possible packages before resolving."""
|
||||
managed_packages: list[str] = []
|
||||
for package in self.packages:
|
||||
managed_package = package.possible()
|
||||
managed_packages.extend(managed_package)
|
||||
|
||||
return managed_packages
|
||||
|
||||
def resolve(self) -> list[str]:
|
||||
"""Return the resolved list of packages to install."""
|
||||
return [package.actual() for package in self.packages]
|
||||
|
||||
def setup(self, old_version):
|
||||
"""Install the packages."""
|
||||
# TODO: Drop the need for setup helper.
|
||||
module_name = self.app.__module__
|
||||
module = sys.modules[module_name]
|
||||
helper = module.setup_helper
|
||||
helper.install(self.packages, skip_recommends=self.skip_recommends)
|
||||
helper.install(self.resolve(), skip_recommends=self.skip_recommends)
|
||||
|
||||
def diagnose(self):
|
||||
"""Run diagnostics and return results."""
|
||||
results = super().diagnose()
|
||||
cache = apt.Cache()
|
||||
for package_name in self.packages:
|
||||
# XXX: Needs to be able to handle missing packages.
|
||||
for package_name in self.resolve():
|
||||
result = 'warning'
|
||||
latest_version = '?'
|
||||
if package_name in cache:
|
||||
@ -187,9 +209,12 @@ class Packages(app.FollowerComponent):
|
||||
return None
|
||||
|
||||
# List of all packages from all Package components
|
||||
cache = apt.Cache()
|
||||
return any(package for package in self.packages
|
||||
if package not in cache)
|
||||
try:
|
||||
self.resolve()
|
||||
except MissingPackageError:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class PackageException(Exception):
|
||||
|
||||
@ -53,8 +53,8 @@ class TestPackageExpressions(unittest.TestCase):
|
||||
def test_packages_init():
|
||||
"""Test initialization of packages component."""
|
||||
component = Packages('test-component', ['foo', 'bar'])
|
||||
assert component.managed_packages() == ['foo', 'bar']
|
||||
assert component.component_id == 'test-component'
|
||||
assert component.packages == ['foo', 'bar']
|
||||
assert not component.skip_recommends
|
||||
assert component.conflicts is None
|
||||
assert component.conflicts_action is None
|
||||
@ -65,12 +65,27 @@ def test_packages_init():
|
||||
component = Packages('test-component', [], skip_recommends=True,
|
||||
conflicts=['conflict1', 'conflict2'],
|
||||
conflicts_action=Packages.ConflictsAction.IGNORE)
|
||||
assert component.packages == []
|
||||
assert component.managed_packages() == []
|
||||
assert component.skip_recommends
|
||||
assert component.conflicts == ['conflict1', 'conflict2']
|
||||
assert component.conflicts_action == Packages.ConflictsAction.IGNORE
|
||||
|
||||
|
||||
def test_packages_resolve():
|
||||
"""Test resolving of package expressions."""
|
||||
component = Packages('test-component', ['python3'])
|
||||
assert component.resolve() == ['python3']
|
||||
|
||||
component = Packages('test-component',
|
||||
[Package('unknown-package') | Package('python3')])
|
||||
assert component.resolve() == ['python3']
|
||||
|
||||
component = Packages('test-component', [], skip_recommends=True,
|
||||
conflicts=['conflict1', 'conflict2'],
|
||||
conflicts_action=Packages.ConflictsAction.IGNORE)
|
||||
assert component.resolve() == []
|
||||
|
||||
|
||||
def test_packages_setup():
|
||||
"""Test setting up packages component."""
|
||||
|
||||
@ -78,22 +93,31 @@ def test_packages_setup():
|
||||
"""Test app"""
|
||||
app_id = 'test-app'
|
||||
|
||||
component = Packages('test-component', ['foo1', 'bar1'])
|
||||
component = Packages('test-component', ['python3', 'bash'])
|
||||
app = TestApp()
|
||||
app.add(component)
|
||||
setup_helper.reset_mock()
|
||||
app.setup(old_version=3)
|
||||
setup_helper.install.assert_has_calls(
|
||||
[call(['foo1', 'bar1'], skip_recommends=False)])
|
||||
[call(['python3', 'bash'], skip_recommends=False)])
|
||||
|
||||
component = Packages('test-component', ['foo2', 'bar2'],
|
||||
component = Packages('test-component', ['bash', 'perl'],
|
||||
skip_recommends=True)
|
||||
app = TestApp()
|
||||
app.add(component)
|
||||
setup_helper.reset_mock()
|
||||
app.setup(old_version=3)
|
||||
setup_helper.install.assert_has_calls(
|
||||
[call(['foo2', 'bar2'], skip_recommends=True)])
|
||||
[call(['bash', 'perl'], skip_recommends=True)])
|
||||
|
||||
component = Packages('test-component',
|
||||
[Package('python3') | Package('unknown-package')])
|
||||
app = TestApp()
|
||||
app.add(component)
|
||||
setup_helper.reset_mock()
|
||||
app.setup(old_version=3)
|
||||
setup_helper.install.assert_has_calls(
|
||||
[call(['python3'], skip_recommends=False)])
|
||||
|
||||
|
||||
@patch('apt.Cache')
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user