• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

thunze / diskfs / 8087910864

28 Feb 2024 10:24PM UTC coverage: 53.54% (+0.07%) from 53.471%
8087910864

push

github

thunze
Minor cosmetic change in `pyproject.toml`

1898 of 3545 relevant lines covered (53.54%)

4.4 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

46.84
/diskfs/table.py
1
"""Protocols implemented in the `table` package and various partition entry checks."""
2

3
from __future__ import annotations
9✔
4

5
import warnings
9✔
6
from enum import Enum
9✔
7
from typing import TYPE_CHECKING, Any, Iterable, Protocol
9✔
8

9
from .base import AlignmentWarning, BoundsError, BoundsWarning, SectorSize
9✔
10

11
if TYPE_CHECKING:
12
    from .disk import Disk
13

14
__all__ = [
9✔
15
    "Table",
16
    "TableType",
17
    "PartitionEntry",
18
    "check_alignment",
19
    "check_bounds",
20
    "check_overlapping",
21
]
22

23

24
class TableType(Enum):
9✔
25
    """Partition table type."""
26

27
    MBR = 0
9✔
28
    GPT = 1
9✔
29

30

31
# noinspection PyPropertyDefinition
32
class PartitionEntry(Protocol):
9✔
33
    """Partition entry in a partition table."""
34

35
    @classmethod
9✔
36
    def new_empty(cls) -> PartitionEntry:
9✔
37
        """New empty / unused partition entry."""
38
        ...
×
39

40
    @classmethod
9✔
41
    def from_bytes(cls, b: bytes) -> PartitionEntry:
9✔
42
        """Parse partition entry from `bytes`."""
43
        ...
×
44

45
    def __bytes__(self) -> bytes:
9✔
46
        """Get `bytes` representation of partition entry."""
47
        ...
×
48

49
    @property
9✔
50
    def start_lba(self) -> int:
9✔
51
        """Starting sector of the partition. Inclusive."""
52
        ...
×
53

54
    @property
9✔
55
    def end_lba(self) -> int:
9✔
56
        """Ending sector of the partition. Inclusive."""
57
        ...
×
58

59
    @property
9✔
60
    def length_lba(self) -> int:
9✔
61
        """Length of the partition in logical sectors."""
62
        ...
×
63

64
    @property
9✔
65
    def type(self) -> Any:
9✔
66
        """Partition type."""
67
        ...
×
68

69
    @property
9✔
70
    def empty(self) -> bool:
9✔
71
        """Whether the partition entry is considered empty / unused."""
72
        ...
×
73

74

75
# noinspection PyPropertyDefinition
76
class Table(Protocol):
9✔
77
    """Partition table."""
78

79
    @classmethod
9✔
80
    def from_disk(cls, disk: Disk) -> Table:
9✔
81
        """Parse partition table from `disk`."""
82
        ...
×
83

84
    def _write_to_disk(self, disk: Disk) -> None:
9✔
85
        """Write partition table to `disk`."""
86
        ...
×
87

88
    def usable_lba(self, disk_size: int, sector_size: SectorSize) -> tuple[int, int]:
9✔
89
        """Return a `tuple` of the first and last logical sector which may be used
90
        by a partition of this partition table.
91
        """
92
        ...
×
93

94
    @property
9✔
95
    def type(self) -> TableType:
9✔
96
        """Partition table type."""
97
        ...
×
98

99
    @property
9✔
100
    def partitions(self) -> tuple[PartitionEntry, ...]:
9✔
101
        ...
×
102

103

104
def check_overlapping(
9✔
105
    partitions: Iterable[PartitionEntry], *, warn: bool = False
106
) -> None:
107
    """Check if the partitions' bounds don't overlap with each other.
108

109
    By default, `BoundsError` is raised if any partitions are found to overlap with
110
    each other. If `warn` is `True`, `BoundsWarning` is emitted instead of
111
    raising an exception.
112
    """
113
    partitions = tuple(partitions)
×
114
    # sort by starting sector
115
    partitions_sorted = sorted(partitions, key=lambda p: p.start_lba)
×
116
    prev_partition_end_lba = 0  # last sector of previous partition
×
117
    overlapping = False
×
118

119
    for partition in partitions_sorted:
×
120
        # Note: end_lba >= start_lba is already checked within the respective
121
        # PartitionEntry class.
122
        if partition.start_lba <= prev_partition_end_lba:
×
123
            overlapping = True
×
124
            break
×
125
        prev_partition_end_lba = partition.end_lba
×
126

127
    if overlapping:
×
128
        message = "At least one partition overlaps another partition"
×
129
        if warn:
×
130
            warnings.warn(message, BoundsWarning)
×
131
        else:
132
            raise BoundsError(message)
×
133

134

135
def check_bounds(
9✔
136
    partition: PartitionEntry, min_lba: int, max_lba: int, *, warn: bool = False
137
) -> None:
138
    """Check if a partition's bounds fall within the range of `(min_lba, max_lba)`.
139

140
    Both `min_lba` and `max_lba` are *inclusive*.
141

142
    By default, `BoundsError` is raised if the partition doesn't fall within the.
143
    range of `(min_lba, max_lba)`. If `warn` is `True`, `BoundsWarning` is emitted
144
    instead of raising an exception.
145
    """
146
    start = partition.start_lba
×
147
    end = partition.end_lba
×
148

149
    if start < min_lba or end > max_lba:
×
150
        message = (
×
151
            f"Partition with bounds (LBA {start}, LBA {end}) does not fall within "
152
            f"the allowed range of (LBA {min_lba}, LBA {max_lba})"
153
        )
154
        if warn:
×
155
            warnings.warn(message, BoundsWarning)
×
156
        else:
157
            raise BoundsError(message)
×
158

159

160
def check_alignment(
9✔
161
    partition: PartitionEntry, sector_size: SectorSize, *, warn: bool = False
162
) -> bool:
163
    """Check if a partition's bounds align to the physical sector size of a disk.
164

165
    Returns `True` or `False` depending on whether the partition is properly aligned.
166

167
    If `warn` is `True`, `AlignmentWarning` is emitted if the partition is not
168
    properly aligned.
169
    """
170
    lss, pss = sector_size
×
171
    start_byte = partition.start_lba * lss
×
172
    end_byte = (partition.end_lba + 1) * lss  # exclusive
×
173

174
    if start_byte % pss != 0 or end_byte % pss != 0:
×
175
        if warn:
×
176
            warnings.warn(
×
177
                f"Partition with bounds ({start_byte}, {end_byte}) is not aligned to "
178
                f"physical sector size of {pss} bytes. This might lead to poor "
179
                f"I/O performance.",
180
                AlignmentWarning,
181
            )
182
        return False
×
183
    return True
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc