From d7a63605002168c633f836e1f57f3b1ce36bc8f4 Mon Sep 17 00:00:00 2001 From: dormant-user Date: Wed, 1 Jan 2025 22:30:40 -0600 Subject: [PATCH] Update disk models for macOS --- pyudisk/main.py | 8 +- pyudisk/models/darwin.py | 290 +++++++++++++++++++++++++++++++++++++++ pyudisk/util.py | 2 +- 3 files changed, 297 insertions(+), 3 deletions(-) diff --git a/pyudisk/main.py b/pyudisk/main.py index a45e9e3..0000ddd 100644 --- a/pyudisk/main.py +++ b/pyudisk/main.py @@ -360,7 +360,9 @@ def monitor_disk(env: EnvConfig) -> Generator[linux.Disk]: Disk: Data structure parsed as a Disk object. """ - assert OPERATING_SYSTEM == OperationSystem.linux, "Monitoring feature is available only for Linux machines!!" + assert ( + OPERATING_SYSTEM == OperationSystem.linux + ), "Monitoring feature is available only for Linux machines!!" message = "" for disk in smart_metrics(env): if disk.Attributes: @@ -393,7 +395,9 @@ def monitor(**kwargs) -> None: Args: **kwargs: Arbitrary keyword arguments. """ - assert OPERATING_SYSTEM == OperationSystem.linux, "Monitoring feature is available only for Linux machines!!" + assert ( + OPERATING_SYSTEM == OperationSystem.linux + ), "Monitoring feature is available only for Linux machines!!" env = EnvConfig(**kwargs) disk_report = [disk.model_dump() for disk in monitor_disk(env)] if disk_report: diff --git a/pyudisk/models/darwin.py b/pyudisk/models/darwin.py index 574f72d..70aa337 100644 --- a/pyudisk/models/darwin.py +++ b/pyudisk/models/darwin.py @@ -155,6 +155,281 @@ class PowerOnTime(BaseModel): hours: Optional[int] = None +# Begin ATA based +class WWN(BaseModel): + """WWN information for the disk. + + >>> WWN + + """ + + naa: Optional[int] = None + oui: Optional[int] = None + id: Optional[int] = None + + +class UserCapacity(BaseModel): + """User capacity information for the disk. + + >>> UserCapacity + + """ + + blocks: Optional[int] = None + bytes: Optional[int] = None + + +class Trim(BaseModel): + """TRIM support information for the disk. + + >>> Trim + + """ + + supported: Optional[bool] = None + deterministic: Optional[bool] = None + zeroed: Optional[bool] = None + + +class ATAVersion(BaseModel): + """ATA version information. + + >>> ATAVersion + + """ + + string: Optional[str] = None + major_value: Optional[int] = None + minor_value: Optional[int] = None + + +class InterfaceSpeedOptions(BaseModel): + """Interface speed options for the disk. + + >>> InterfaceSpeedOptions + + """ + + sata_value: Optional[int] = None + string: Optional[str] = None + units_per_second: Optional[int] = None + bits_per_unit: Optional[int] = None + + +class InterfaceSpeed(BaseModel): + """Interface speed information for the disk. + + >>> InterfaceSpeed + + """ + + max: Optional[InterfaceSpeedOptions] = None + current: Optional[InterfaceSpeedOptions] = None + + +class GenericStatus(BaseModel): + """Generic status information. + + >>> GenericStatus + + """ + + value: Optional[int | str] = None + string: Optional[int | str] = None + + +class STStatus(BaseModel): + """Self-test status information. + + >>> STStatus + + """ + + value: Optional[int] = None + string: Optional[str] = None + passed: Optional[bool] = None + + +class OfflineDataCollection(BaseModel): + """Offline data collection information. + + >>> OfflineDataCollection + + """ + + status: Optional[GenericStatus] = None + completion_seconds: Optional[int] = None + + +class PollingMinutes(BaseModel): + """Polling minutes information. + + >>> PollingMinutes + + """ + + short: Optional[int] = None + extended: Optional[int] = None + + +class SelfTest(BaseModel): + """Self-test information. + + >>> SelfTest + + """ + + status: Optional[STStatus] = None + polling_minutes: Optional[PollingMinutes] = None + + +class Capabilities(BaseModel): + """Capabilities information. + + >>> Capabilities + + """ + + values: List[int] = None + exec_offline_immediate_supported: Optional[bool] = None + offline_is_aborted_upon_new_cmd: Optional[bool] = None + offline_surface_scan_supported: Optional[bool] = None + self_tests_supported: Optional[bool] = None + conveyance_self_test_supported: Optional[bool] = None + selective_self_test_supported: Optional[bool] = None + attribute_autosave_enabled: Optional[bool] = None + error_logging_supported: Optional[bool] = None + gp_logging_supported: Optional[bool] = None + + +class ATASmartData(BaseModel): + """ATA SMART data information. + + >>> ATASmartData + + """ + + offline_data_collection: Optional[OfflineDataCollection] = None + self_test: Optional[SelfTest] = None + capabilities: Optional[Capabilities] = None + + +class Flags(BaseModel): + """Flags information. + + >>> Flags + + """ + + value: Optional[int] = None + string: Optional[str] = None + prefailure: Optional[bool] = None + updated_online: Optional[bool] = None + performance: Optional[bool] = None + error_rate: Optional[bool] = None + event_count: Optional[bool] = None + auto_keep: Optional[bool] = None + + +class ATATable(BaseModel): + """ATA table information. + + >>> ATATable + + """ + + id: Optional[int] = None + name: Optional[str] = None + value: Optional[int] = None + worst: Optional[int] = None + thresh: Optional[int] = None + when_failed: Optional[str] = None + flags: Optional[Flags] = None + raw: Optional[GenericStatus] = None + + +class ATASmartAttributes(BaseModel): + """ATA SMART attributes information. + + >>> ATASmartAttributes + + """ + + revision: Optional[int] = None + table: Optional[List[ATATable]] = None + + +class ATASmartLog(BaseModel): + """ATA SMART log information. + + >>> ATASmartLog + + """ + + revision: Optional[int] = None + count: Optional[int] = None + + +class ATASummary(BaseModel): + """ATA summary information. + + >>> ATASummary + + """ + + summary: Optional[ATASmartLog] = None + + +class ATAStandard(BaseModel): + """ATA standard information. + + >>> ATAStandard + + """ + + standard: Optional[ATASmartLog] = None + + +class ATASmartSelectiveSelfTestLogTable(BaseModel): + """ATA SMART selective self-test log table information. + + >>> ATASmartSelectiveSelfTestLogTable + + """ + + lba_min: Optional[int] = None + lba_max: Optional[int] = None + status: Optional[GenericStatus] = None + + +class ATASmartSelectiveSelfTestFlags(BaseModel): + """ATA SMART selective self-test flags information. + + >>> ATASmartSelectiveSelfTestFlags + + """ + + value: Optional[int] = None + reminder_scan_enabled: Optional[bool] = None + + +class ATASmartSelectiveSelfTestLog(BaseModel): + """ATA SMART selective self-test log information. + + >>> ATASmartSelectiveSelfTestLog + + """ + + revision: Optional[int] = None + table: List[ATASmartSelectiveSelfTestLogTable] = None + current_read_scan: Optional[ATASmartSelectiveSelfTestLogTable] = None + flags: Optional[ATASmartSelectiveSelfTestFlags] = None + power_up_scan_resume_minutes: Optional[int] = None + + +# End ATA based + + class Disk(BaseModel): """Collective disk information. @@ -166,9 +441,20 @@ class Disk(BaseModel): smartctl: Optional[SmartCTL] = None local_time: Optional[LocalTime] = None device: Optional[Device] = None + model_family: Optional[str] = None model_name: Optional[str] = None serial_number: Optional[str] = None + wwn: Optional[WWN] = None firmware_version: Optional[str] = None + user_capacity: Optional[UserCapacity] = None + logical_block_size: Optional[int] = None + physical_block_size: Optional[int] = None + rotation_rate: Optional[int] = None + trim: Optional[Trim] = None + in_smartctl_database: Optional[bool] = None + ata_version: Optional[ATAVersion] = None + sata_version: Optional[GenericStatus] = None + interface_speed: Optional[InterfaceSpeed] = None nvme_pci_vendor: Optional[NvmePciVendor] = None nvme_ieee_oui_identifier: Optional[int] = None nvme_controller_id: Optional[int] = None @@ -176,10 +462,14 @@ class Disk(BaseModel): nvme_number_of_namespaces: Optional[int] = None smart_support: Optional[SmartSupport] = None smart_status: Optional[SmartStatus] = None + ata_smart_data: Optional[ATASmartData] = None nvme_smart_health_information_log: Optional[NvmeSmartHealthInformationLog] = None temperature: Optional[Temperature] = None power_cycle_count: Optional[int] = None power_on_time: Optional[PowerOnTime] = None + ata_smart_error_log: Optional[ATASummary] = None + ata_smart_self_test_log: Optional[ATAStandard] = None + ata_smart_selective_self_test_log: Optional[ATASmartSelectiveSelfTestLog] = None usage: Optional[Usage] = None class Config: diff --git a/pyudisk/util.py b/pyudisk/util.py index 20b4a1e..dbd7be8 100644 --- a/pyudisk/util.py +++ b/pyudisk/util.py @@ -32,7 +32,7 @@ def celsius_to_kelvin(celsius: int | float): def celsius_to_fahrenheit(celsius: int | float): """Convert Celsius to Fahrenheit.""" - fahrenheit = (celsius * 9/5) + 32 + fahrenheit = (celsius * 9 / 5) + 32 return fahrenheit