Problem
The following code I am using to lookup the description based on a “Partition Type” in either a string, an integer or hex value. By calling parttype(parttype)
in the below code.
Is there a more pythonic way for this?
__PARTTYPE_TO_DESCRIPTION__ = {
"00": "Empty",
"01": "DOS 12-bit FAT",
"02": "XENIX root",
"03": "XENIX /usr",
"04": "DOS 3.0+ 16-bit FAT (up to 32M)",
"05": "DOS 3.3+ Extended Partition",
"06": "DOS 3.31+ 16-bit FAT (over 32M)",
"07": "Windows NTFS | OS/2 IFS | exFAT | Advanced Unix | QNX2.x pre-1988",
"08": "AIX boot | OS/2 (v1.0-1.3 only) | SplitDrive | Commodore DOS | DELL partition spanning multiple drives | QNX 1.x and 2.x ('qny')",
"09": "AIX data | Coherent filesystem | QNX 1.x and 2.x ('qnz')",
"0a": "OS/2 Boot Manager | Coherent swap partition | OPUS",
"0b": "WIN95 OSR2 FAT32",
"0c": "WIN95 OSR2 FAT32, LBA-mapped",
"0d": "SILICON SAFE",
"0e": "WIN95: DOS 16-bit FAT, LBA-mapped",
"0f": "WIN95: Extended partition, LBA-mapped",
"10": "OPUS (? - not certain - ?)",
"11": "Hidden DOS 12-bit FAT | Leading Edge DOS 3.x logically sectored FAT",
"12": "Configuration/diagnostics partition",
"14": "Hidden DOS 16-bit FAT <32M | AST DOS with logically sectored FAT",
"16": "Hidden DOS 16-bit FAT >=32M",
"17": "Hidden IFS",
"18": "AST SmartSleep Partition",
"19": "Claimed for Willowtech Photon coS",
"1b": "Hidden WIN95 OSR2 FAT32",
"1c": "Hidden WIN95 OSR2 FAT32, LBA-mapped",
"1e": "Hidden WIN95 16-bit FAT, LBA-mapped",
"20": "Rumoured to be used by Willowsoft Overture File System",
"21": "Reserved for: HP Volume Expansion, SpeedStor variant | Claimed for FSo2 (Oxygen File System)",
"22": "Claimed for Oxygen Extended Partition Table",
"23": "Reserved - unknown",
"24": "NEC DOS 3.x",
"26": "Reserved - unknown",
"27": "PQservice | Windows RE hidden partition | MirOS partition | RouterBOOT kernel partition",
"2a": "AtheOS File System (AFS)",
"2b": "SyllableSecure (SylStor)",
"31": "Reserved - unknown",
"32": "NOS",
"33": "Reserved - unknown",
"34": "Reserved - unknown",
"35": "JFS on OS/2 or eCS ",
"36": "Reserved - unknown",
"38": "THEOS ver 3.2 2gb partition",
"39": "Plan 9 partition | THEOS ver 4 spanned partition",
"3a": "THEOS ver 4 4gb partition",
"3b": "THEOS ver 4 extended partition",
"3c": "PartitionMagic recovery partition",
"3d": "Hidden NetWare",
"40": "Venix 80286 | PICK | Linux/MINIX",
"41": "Personal RISC Boot | PPC PReP (Power PC Reference Platform) Boot",
"42": "Windows dynamic extended partition | Linux swap | SFS (Secure Filesystem)",
"43": "Linux native",
"44": "GoBack partition",
"45": "Boot-US boot manager | Priam | EUMEL/Elan ",
"46": "EUMEL/Elan",
"47": "EUMEL/Elan",
"48": "EUMEL/Elan",
"4a": "Mark Aitchison's ALFS/THIN lightweight filesystem for DOS | AdaOS Aquila (Withdrawn)",
"4c": "Oberon partition",
"4d": "QNX4.x",
"4e": "QNX4.x 2nd part",
"4f": "QNX4.x 3rd part | Oberon partition",
"50": "OnTrack Disk Manager (older versions) RO | Lynx RTOS | Native Oberon (alt)",
"51": "OnTrack Disk Manager RW (DM6 Aux1) | Novell",
"52": "CP/M | Microport SysV/AT",
"53": "Disk Manager 6.0 Aux3",
"54": "Disk Manager 6.0 Dynamic Drive Overlay (DDO)",
"55": "EZ-Drive",
"56": "Golden Bow VFeature Partitioned Volume | DM converted to EZ-BIOS | AT&T MS-DOS 3.x logically sectored FAT",
"57": "DrivePro | VNDI Partition",
"5c": "Priam EDisk",
"61": "SpeedStor",
"63": "Unix System V (SCO, ISC Unix, UnixWare, ...), Mach, GNU Hurd",
"64": "PC-ARMOUR protected partition | Novell Netware 286, 2.xx",
"65": "Novell Netware 386, 3.xx or 4.xx",
"66": "Novell Netware SMS Partition",
"67": "Novell",
"68": "Novell",
"69": "Novell Netware 5+, Novell Netware NSS Partition",
"70": "DiskSecure Multi-Boot",
"71": "Reserved - unknown",
"72": "V7/x86",
"73": "Reserved - unknown",
"74": "Scramdisk partition | Reserved - unknown",
"75": "IBM PC/IX",
"76": "Reserved - unknown",
"77": "M2FS/M2CS partition | VNDI Partition",
"78": "XOSL FS",
"7e": "Claimed for F.I.X.",
"7f": "Proposed for the Alt-OS-Development Partition Standard",
"80": "MINIX until 1.4a",
"81": "MINIX since 1.4b, early Linux | Mitac disk manager",
"82": "Linux swap | Solaris x86 | Prime",
"83": "Linux native partition",
"84": "OS/2 hidden C: drive | Hibernation partition",
"85": "Linux extended partition",
"86": "Old Linux RAID partition superblock | FAT16 volume set",
"87": "NTFS volume set",
"88": "Linux plaintext partition table",
"8a": "Linux Kernel Partition (used by AiR-BOOT)",
"8b": "Legacy Fault Tolerant FAT32 volume",
"8c": "Legacy Fault Tolerant FAT32 volume using BIOS extd INT 13h",
"8d": "Free FDISK 0.96+ hidden Primary DOS FAT12 partitition",
"8e": "Linux Logical Volume Manager partition",
"90": "Free FDISK 0.96+ hidden Primary DOS FAT16 partitition",
"91": "Free FDISK 0.96+ hidden DOS extended partitition",
"92": "Free FDISK 0.96+ hidden Primary DOS large FAT16 partitition",
"93": "Hidden Linux native partition | Amoeba",
"94": "Amoeba bad block table",
"95": "MIT EXOPC native partitions",
"96": "CHRP ISO-9660 filesystem",
"97": "Free FDISK 0.96+ hidden Primary DOS FAT32 partitition",
"98": "Free FDISK 0.96+ hidden Primary DOS FAT32 partitition (LBA) | Datalight ROM-DOS Super-Boot Partition",
"99": "DCE376 logical drive",
"9a": "Free FDISK 0.96+ hidden Primary DOS FAT16 partitition (LBA)",
"9b": "Free FDISK 0.96+ hidden DOS extended partitition (LBA)",
"9e": "ForthOS partition",
"9f": "BSD/OS",
"a0": "Laptop hibernation partition",
"a1": "Laptop hibernation partition | HP Volume Expansion (SpeedStor variant)",
"a3": "HP Volume Expansion (SpeedStor variant)",
"a4": "HP Volume Expansion (SpeedStor variant)",
"a5": "BSD/386, 386BSD, NetBSD, FreeBSD",
"a6": "OpenBSD | HP Volume Expansion (SpeedStor variant)",
"a7": "NeXTStep",
"a8": "Mac OS-X",
"a9": "NetBSD",
"aa": "Olivetti Fat 12 1.44MB Service Partition",
"ab": "Mac OS-X Boot partition | GO! partition",
"ad": "RISC OS ADFS",
"ae": "ShagOS filesystem",
"af": "MacOS X HFS | ShagOS swap partition",
"b0": "BootStar Dummy",
"b1": "HP Volume Expansion (SpeedStor variant) | QNX Neutrino Power-Safe filesystem",
"b2": "QNX Neutrino Power-Safe filesystem",
"b3": "HP Volume Expansion (SpeedStor variant) | QNX Neutrino Power-Safe filesystem",
"b4": "HP Volume Expansion (SpeedStor variant)",
"b6": "HP Volume Expansion (SpeedStor variant) | Corrupted Windows NT mirror set (master), FAT16 file system",
"b7": "Corrupted Windows NT mirror set (master), NTFS file system | BSDI BSD/386 filesystem",
"b8": "BSDI BSD/386 swap partition",
"bb": "Boot Wizard hidden",
"bc": "Acronis backup partition",
"bd": "BonnyDOS/286",
"be": "Solaris 8 boot partition",
"bf": "New Solaris x86 partition",
"c0": "CTOS | REAL/32 secure small partition | NTFT Partition | DR-DOS/Novell DOS secured partition",
"c1": "DRDOS/secured (FAT-12)",
"c2": "Hidden Linux",
"c3": "Hidden Linux swap",
"c4": "DRDOS/secured (FAT-16, < 32M)",
"c5": "DRDOS/secured (extended)",
"c6": "DRDOS/secured (FAT-16, >= 32M) | Windows NT corrupted FAT16 volume/stripe set",
"c7": "Windows NT corrupted NTFS volume/stripe set | Syrinx boot",
"c8": "Reserved for DR-DOS 8.0+",
"c9": "Reserved for DR-DOS 8.0+",
"ca": "Reserved for DR-DOS 8.0+",
"cb": "DR-DOS 7.04+ secured FAT32 (CHS)",
"cc": "DR-DOS 7.04+ secured FAT32 (LBA)",
"cd": "CTOS Memdump",
"ce": "DR-DOS 7.04+ FAT16X (LBA)",
"cf": "DR-DOS 7.04+ secured EXT DOS (LBA)",
"d0": "REAL/32 secure big partition | Multiuser DOS secured partition",
"d1": "Old Multiuser DOS secured FAT12",
"d4": "Old Multiuser DOS secured FAT16 <32M",
"d5": "Old Multiuser DOS secured extended partition",
"d6": "Old Multiuser DOS secured FAT16 >=32M",
"d8": "CP/M-86",
"da": "Non-FS Data | Powercopy Backup",
"db": "Digital Research CP/M, Concurrent CP/M, Concurrent DOS | CTOS (Convergent Technologies OS -Unisys) | KDG Telemetry SCPU boot",
"dd": "Hidden CTOS Memdump",
"de": "Dell PowerEdge Server utilities (FAT fs)",
"df": "DG/UX virtual disk manager partition | BootIt EMBRM",
"e0": "Reserved by STMicroelectronics for a filesystem called ST AVFS",
"e1": "DOS access or SpeedStor 12-bit FAT extended partition",
"e3": "DOS R/O | SpeedStor",
"e4": "SpeedStor 16-bit FAT extended partition < 1024 cyl.",
"e5": "Tandy MSDOS with logically sectored FAT",
"e6": "Storage Dimensions SpeedStor",
"e8": "LUKS",
"eb": "BeOS BFS",
"ec": "SkyOS SkyFS",
"ed": "plans to use this for an OS called Sprytix",
"ee": "Indication that this legacy MBR is followed by an EFI header",
"ef": "Partition that contains an EFI file system",
"f0": "Linux/PA-RISC boot loader",
"f1": "Storage Dimensions SpeedStor",
"f2": "DOS 3.3+ secondary partition",
"f3": "Storage Dimensions SpeedStor",
"f4": "SpeedStor large partition | Prologue single-volume partition",
"f5": "Prologue multi-volume partition",
"f6": "Storage Dimensions SpeedStor",
"f7": "DDRdrive Solid State File System",
"f9": "pCache",
"fa": "Bochs",
"fb": "VMware File System partition",
"fc": "VMware Swap partition",
"fd": "Linux raid partition with autodetect using persistent superblock",
"fe": "SpeedStor > 1024 cyl. | LANstep | IBM PS/2 IML (Initial Microcode Load) partition, located at the end of the disk. | Windows NT Disk Administrator hidden partition | Linux Logical Volume Manager partition (old)",
"ff": "Xenix Bad Block Table"}
def parttype_2_description(parttype):
try:
"""
returns the Partition Type Description
based on a two character (hex) string Partition type
"""
return __PARTTYPE_TO_DESCRIPTION__[parttype.lower()]
except KeyError:
return 'Unknown partition type: ' + parttype.lower()
def parttype_int_2_description(parttype):
"""
returns the Partition Type Description
based on an integer partition type
"""
return parttype_2_description(str(hex(parttype))[2:].rjust(2, '0'))
def parttype_hex_2_description(parttype):
"""
returns the Partition Type Descriptoin
based on a hex partition type
"""
return parttype_2_description(str(parttype)[2:].rjust(2, '0'))
def ishex(value):
if not str(value)[:2] == '0x':
return False
try:
hexval = int(value, 16)
return True
except:
return False
def isint(value):
return isinstance(value, int)
def isstr(value):
return isinstance(value, str)
def parttype(parttype):
"""
returns the partition type descriptor based on
a string, int or hex partition type
"""
if ishex(parttype): return parttype_hex_2_description(parttype)
if isint(parttype): return parttype_int_2_description(parttype)
if isstr(parttype): return parttype_2_description(parttype)
return
def main():
print('do not run this interactively')
print('import and call the parttype() function')
return
if __name__ == '__main__':
main ()
Solution
The dictionary
The naming rules in PEP 8 state:
__double_leading_and_trailing_underscore__
: “magic” objects or attributes that live in user-controlled namespaces. E.g.__init__
,__import__
or__file__
. Never invent such names; only use them as documented.
If your intention is to simply indicate that the dictionary is “private”, use a _single_leading_underscore
. Coupled with the convention to use ALL_CAPS
for constants, I would name it _PARTTYPE_TO_DESCRIPTION
.
The keys in the dictionary represent numbers, right? Then why not write them as numbers? It is easier to normalize strings into integers than to format integers as strings, since there are a multitude ways to write 15
(e.g. "0f"
, "0F"
, "0x0f"
, "0x0F"
).
The lookup functions
I’m not a fan of the parttype_…_2_description(…)
naming. The 2
looks like it’s supposed to be some version number.
Instead of three lookup functions, why not offer one function that just does the “right thing” depending on the argument value?
I don’t think that you should return 'Unknown partition type: 13'
as if it were a valid result. You could either raise an exception, or let the caller specify the fallback value. When composing the exception string, don’t mess with the input (.lower()
) — it’s confusing.
The parttype_2_description
docstring is botched. It needs to be the very first thing inside the function.
Suggested solution
I would write one function that handles all the cases, and include a docstring with doctests to thoroughly describe how to use it.
_PARTTYPE_TO_DESCRIPTION = {
0x00: "Empty",
0x01: "DOS 12-bit FAT",
0x02: "XENIX root",
0x03: "XENIX /usr",
0x04: "DOS 3.0+ 16-bit FAT (up to 32M)",
0x05: "DOS 3.3+ Extended Partition",
0x06: "DOS 3.31+ 16-bit FAT (over 32M)",
0x07: "Windows NTFS | OS/2 IFS | exFAT | Advanced Unix | QNX2.x pre-1988",
0x08: "AIX boot | OS/2 (v1.0-1.3 only) | SplitDrive | Commodore DOS | DELL partition spanning multiple drives | QNX 1.x and 2.x ('qny')",
0x09: "AIX data | Coherent filesystem | QNX 1.x and 2.x ('qnz')",
0x0A: "OS/2 Boot Manager | Coherent swap partition | OPUS",
0x0B: "WIN95 OSR2 FAT32",
0x0C: "WIN95 OSR2 FAT32, LBA-mapped",
0x0D: "SILICON SAFE",
0x0E: "WIN95: DOS 16-bit FAT, LBA-mapped",
0x0F: "WIN95: Extended partition, LBA-mapped",
0x10: "OPUS (? - not certain - ?)",
…
0xFF: "Xenix Bad Block Table",
}
def partition_description(type, unknown_description=None):
"""
Return the Partition Type Description for the partition type, given either
as an integer or as a hex string.
>>> partition_description(15)
'WIN95: Extended partition, LBA-mapped'
>>> partition_description(0x0f)
'WIN95: Extended partition, LBA-mapped'
>>> partition_description('0x0f')
'WIN95: Extended partition, LBA-mapped'
>>> partition_description('0x0F')
'WIN95: Extended partition, LBA-mapped'
>>> partition_description('0F')
'WIN95: Extended partition, LBA-mapped'
>>> partition_description('0f')
'WIN95: Extended partition, LBA-mapped'
If unknown_description is also given, then it will be returned if there is
no such partition type.
>>> partition_description(0x13, 'Bogus partition!')
'Bogus partition!'
If unknown_description is None or is omitted, then ValueError will be
raised for unrecognized partition types.
>>> partition_description('0x13')
Traceback (most recent call last):
...
ValueError: Unknown partition type: 0x13
"""
type_num = type if isinstance(type, int) else int(type, base=16)
description = _PARTTYPE_TO_DESCRIPTION.get(type_num, unknown_description)
if description is None:
raise ValueError('Unknown partition type: ' + str(type))
return description