make annotations a functools.singledispatch

This commit is contained in:
Michael Hudson-Doyle 2021-05-31 16:22:29 +12:00
parent 5b7409750e
commit 55191bafb5
7 changed files with 129 additions and 85 deletions

View File

@ -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

View File

@ -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 <http://www.gnu.org/licenses/>.
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

View File

@ -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

View File

@ -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):

View File

@ -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):

View File

@ -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)),

View File

@ -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)),