From 55191bafb5b11e81260c89525268969aec143313 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Mon, 31 May 2021 16:22:29 +1200 Subject: [PATCH] make annotations a functools.singledispatch --- po/POTFILES.in | 1 + subiquity/common/filesystem/labels.py | 89 +++++++++++++++++++++ subiquity/models/filesystem.py | 62 +------------- subiquity/models/tests/test_filesystem.py | 39 ++++----- subiquity/ui/views/filesystem/filesystem.py | 9 ++- subiquity/ui/views/filesystem/guided.py | 5 +- subiquity/ui/views/filesystem/helpers.py | 9 ++- 7 files changed, 129 insertions(+), 85 deletions(-) create mode 100644 subiquity/common/filesystem/labels.py diff --git a/po/POTFILES.in b/po/POTFILES.in index e00ff1a0..2343cf5a 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -34,6 +34,7 @@ subiquity/common/api/tests/test_server.py subiquity/common/errorreport.py subiquity/common/filesystem/actions.py subiquity/common/filesystem/__init__.py +subiquity/common/filesystem/labels.py subiquity/common/filesystem/manipulator.py subiquity/common/filesystem/tests/__init__.py subiquity/common/filesystem/tests/test_actions.py diff --git a/subiquity/common/filesystem/labels.py b/subiquity/common/filesystem/labels.py new file mode 100644 index 00000000..d899a87f --- /dev/null +++ b/subiquity/common/filesystem/labels.py @@ -0,0 +1,89 @@ +# Copyright 2021 Canonical, Ltd. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +import functools + +from subiquity.models.filesystem import ( + Disk, + LVM_VolGroup, + Partition, + ) + + +def _annotations_generic(device): + preserve = getattr(device, 'preserve', None) + if preserve is None: + return [] + elif preserve: + # A pre-existing device such as a partition or RAID + return [_("existing")] + else: + # A newly created device such as a partition or RAID + return [_("new")] + + +@functools.singledispatch +def annotations(device): + return _annotations_generic(device) + + +@annotations.register(Disk) +def _annotations_disk(disk): + return [] + + +@annotations.register(Partition) +def _annotations_partition(partition): + r = _annotations_generic(partition) + if partition.flag == "prep": + r.append("PReP") + if partition.preserve: + if partition.grub_device: + # boot loader partition + r.append(_("configured")) + else: + # boot loader partition + r.append(_("unconfigured")) + elif partition.is_esp: + if partition.fs() and partition.fs().mount(): + r.append(_("primary ESP")) + elif partition.grub_device: + r.append(_("backup ESP")) + else: + r.append(_("unused ESP")) + elif partition.flag == "bios_grub": + if partition.preserve: + if partition.device.grub_device: + r.append(_("configured")) + else: + r.append(_("unconfigured")) + r.append("bios_grub") + elif partition.flag == "extended": + # extended partition + r.append(_("extended")) + elif partition.flag == "logical": + # logical partition + r.append(_("logical")) + return r + + +@annotations.register(LVM_VolGroup) +def _annotations_vg(vg): + r = _annotations_generic(vg) + member = next(iter(vg.devices)) + if member.type == "dm_crypt": + # Flag for a LVM volume group + r.append(_("encrypted")) + return r diff --git a/subiquity/models/filesystem.py b/subiquity/models/filesystem.py index 0fe03cc3..bd9a1138 100644 --- a/subiquity/models/filesystem.py +++ b/subiquity/models/filesystem.py @@ -429,18 +429,6 @@ class _Formattable(ABC): def label(self): pass - @property - def annotations(self): - preserve = getattr(self, 'preserve', None) - if preserve is None: - return [] - elif preserve: - # A pre-existing device such as a partition or RAID - return [_("existing")] - else: - # A newly created device such as a partition or RAID - return [_("new")] - # Filesystem _fs = attributes.backlink() # Raid or LVM_VolGroup for now, but one day ZPool, BCache... @@ -668,10 +656,6 @@ class Disk(_Device): def size(self): return align_down(self._info.size) - @property - def annotations(self): - return [] - def desc(self): if self.multipath: return _("multipath device") @@ -749,40 +733,6 @@ class Partition(_Formattable): name = attr.ib(default=None) multipath = attr.ib(default=None) - @property - def annotations(self): - r = super().annotations - if self.flag == "prep": - r.append("PReP") - if self.preserve: - if self.grub_device: - # boot loader partition - r.append(_("configured")) - else: - # boot loader partition - r.append(_("unconfigured")) - elif self.is_esp: - if self.fs() and self.fs().mount(): - r.append(_("primary ESP")) - elif self.grub_device: - r.append(_("backup ESP")) - else: - r.append(_("unused ESP")) - elif self.flag == "bios_grub": - if self.preserve: - if self.device.grub_device: - r.append(_("configured")) - else: - r.append(_("unconfigured")) - r.append("bios_grub") - elif self.flag == "extended": - # extended partition - r.append(_("extended")) - elif self.flag == "logical": - # logical partition - r.append(_("logical")) - return r - def usage_labels(self): if self.flag == "prep" or self.flag == "bios_grub": return [] @@ -867,11 +817,12 @@ class Partition(_Formattable): ok_for_lvm_vg = ok_for_raid def for_client(self): + from subiquity.common.filesystem.labels import annotations from subiquity.common.types import Partition return Partition( size=self.size, number=self._number, - annotations=self.annotations + self.usage_labels()) + annotations=annotations(self) + self.usage_labels()) @fsobj("raid") @@ -946,15 +897,6 @@ class LVM_VolGroup(_Device): def available_for_partitions(self): return self.size - @property - def annotations(self): - r = super().annotations - member = next(iter(self.devices)) - if member.type == "dm_crypt": - # Flag for a LVM volume group - r.append(_("encrypted")) - return r - @property def label(self): return self.name diff --git a/subiquity/models/tests/test_filesystem.py b/subiquity/models/tests/test_filesystem.py index 889c771f..9e2e5dd0 100644 --- a/subiquity/models/tests/test_filesystem.py +++ b/subiquity/models/tests/test_filesystem.py @@ -17,6 +17,9 @@ import unittest import attr +from subiquity.common.filesystem.labels import ( + annotations, + ) from subiquity.models.filesystem import ( Bootloader, dehumanize_size, @@ -216,68 +219,68 @@ class TestFilesystemModel(unittest.TestCase): def test_disk_annotations(self): # disks never have annotations model, disk = make_model_and_disk() - self.assertEqual(disk.annotations, []) + self.assertEqual(annotations(disk), []) disk.preserve = True - self.assertEqual(disk.annotations, []) + self.assertEqual(annotations(disk), []) def test_partition_annotations(self): model = make_model() part = make_partition(model) - self.assertEqual(part.annotations, ['new']) + self.assertEqual(annotations(part), ['new']) part.preserve = True - self.assertEqual(part.annotations, ['existing']) + self.assertEqual(annotations(part), ['existing']) model = make_model() part = make_partition(model, flag="bios_grub") self.assertEqual( - part.annotations, ['new', 'bios_grub']) + annotations(part), ['new', 'bios_grub']) part.preserve = True self.assertEqual( - part.annotations, ['existing', 'unconfigured', 'bios_grub']) + annotations(part), ['existing', 'unconfigured', 'bios_grub']) part.device.grub_device = True self.assertEqual( - part.annotations, ['existing', 'configured', 'bios_grub']) + annotations(part), ['existing', 'configured', 'bios_grub']) model = make_model() part = make_partition(model, flag="boot", grub_device=True) - self.assertEqual(part.annotations, ['new', 'backup ESP']) + self.assertEqual(annotations(part), ['new', 'backup ESP']) fs = model.add_filesystem(part, fstype="fat32") model.add_mount(fs, "/boot/efi") - self.assertEqual(part.annotations, ['new', 'primary ESP']) + self.assertEqual(annotations(part), ['new', 'primary ESP']) model = make_model() part = make_partition(model, flag="boot", preserve=True) - self.assertEqual(part.annotations, ['existing', 'unused ESP']) + self.assertEqual(annotations(part), ['existing', 'unused ESP']) part.grub_device = True - self.assertEqual(part.annotations, ['existing', 'backup ESP']) + self.assertEqual(annotations(part), ['existing', 'backup ESP']) fs = model.add_filesystem(part, fstype="fat32") model.add_mount(fs, "/boot/efi") - self.assertEqual(part.annotations, ['existing', 'primary ESP']) + self.assertEqual(annotations(part), ['existing', 'primary ESP']) model = make_model() part = make_partition(model, flag="prep", grub_device=True) - self.assertEqual(part.annotations, ['new', 'PReP']) + self.assertEqual(annotations(part), ['new', 'PReP']) model = make_model() part = make_partition(model, flag="prep", preserve=True) self.assertEqual( - part.annotations, ['existing', 'PReP', 'unconfigured']) + annotations(part), ['existing', 'PReP', 'unconfigured']) part.grub_device = True self.assertEqual( - part.annotations, ['existing', 'PReP', 'configured']) + annotations(part), ['existing', 'PReP', 'configured']) def test_vg_default_annotations(self): model, disk = make_model_and_disk() vg = model.add_volgroup('vg-0', {disk}) - self.assertEqual(vg.annotations, ['new']) + self.assertEqual(annotations(vg), ['new']) vg.preserve = True - self.assertEqual(vg.annotations, ['existing']) + self.assertEqual(annotations(vg), ['existing']) def test_vg_encrypted_annotations(self): model, disk = make_model_and_disk() dm_crypt = model.add_dm_crypt(disk, key='passw0rd') vg = model.add_volgroup('vg-0', {dm_crypt}) - self.assertEqual(vg.annotations, ['new', 'encrypted']) + self.assertEqual(annotations(vg), ['new', 'encrypted']) def _test_ok_for_xxx(self, model, make_new_device, attr, test_partitions=True): diff --git a/subiquity/ui/views/filesystem/filesystem.py b/subiquity/ui/views/filesystem/filesystem.py index f3f5f38d..8f76856c 100644 --- a/subiquity/ui/views/filesystem/filesystem.py +++ b/subiquity/ui/views/filesystem/filesystem.py @@ -63,6 +63,9 @@ from subiquitycore.view import BaseView from subiquity.common.filesystem.actions import ( DeviceAction, ) +from subiquity.common.filesystem.labels import ( + annotations, + ) from subiquity.models.filesystem import ( humanize_size, ) @@ -104,10 +107,10 @@ class MountInfo: @property def desc(self): - annotations = self.mount.device.volume.annotations + anns = annotations(self.mount.device.volume) desc = self.mount.device.volume.desc() - if annotations: - desc = annotations[0] + " " + desc + if anns: + desc = anns[0] + " " + desc return desc def startswith(self, other): diff --git a/subiquity/ui/views/filesystem/guided.py b/subiquity/ui/views/filesystem/guided.py index 3bb6270f..b7862e92 100644 --- a/subiquity/ui/views/filesystem/guided.py +++ b/subiquity/ui/views/filesystem/guided.py @@ -44,6 +44,9 @@ from subiquitycore.ui.utils import ( ) from subiquitycore.view import BaseView +from subiquity.common.filesystem.labels import ( + annotations, + ) from subiquity.common.types import GuidedChoice from subiquity.models.filesystem import humanize_size @@ -90,7 +93,7 @@ def summarize_device(disk): ])] if disk.partitions: for part in disk.partitions: - details = ", ".join(part.annotations) + details = ", ".join(annotations(part)) rows.append((part, [ Text(_("partition {number}").format(number=part.number)), (2, Text(details)), diff --git a/subiquity/ui/views/filesystem/helpers.py b/subiquity/ui/views/filesystem/helpers.py index d4cbd1ea..37f89203 100644 --- a/subiquity/ui/views/filesystem/helpers.py +++ b/subiquity/ui/views/filesystem/helpers.py @@ -19,6 +19,9 @@ from subiquitycore.ui.utils import ( Color, ) +from subiquity.common.filesystem.labels import ( + annotations, + ) from subiquity.models.filesystem import ( humanize_size, ) @@ -34,8 +37,8 @@ def summarize_device(device, part_filter=lambda p: True): out by looking at the uses of this function. """ label = device.label - if device.annotations: - label = "{} ({})".format(label, ", ".join(device.annotations)) + if annotations(device): + label = "{} ({})".format(label, ", ".join(annotations(device))) rows = [(device, [ (2, Text(label)), Text(device.desc()), @@ -46,7 +49,7 @@ def summarize_device(device, part_filter=lambda p: True): for part in device.partitions(): if not part_filter(part): continue - details = ", ".join(part.annotations + part.usage_labels()) + details = ", ".join(annotations(part) + part.usage_labels()) rows.append((part, [ Text(part.short_label), (2, Text(details)),