Skip to main content

Read, inspect, and create Apple DMG files from Python

Project description

pydmg

pydmg is a cross-platform Python library for reading, inspecting, extracting, and creating Apple DMG files. It uses the Rust crate apple-dmg under the hood and exposes a Pythonic API.

  • License: MIT
  • Core Rust dependency: apple-dmg (Apache-2.0 OR MIT, MIT-compatible)
  • HFS+/APFS backend: dpp (MIT)
  • Third-party notices: THIRD_PARTY_NOTICES.md
  • Build backend: maturin + pyo3
  • Platforms: macOS, Linux, Windows
  • Distribution: prebuilt wheels for major architectures + source distribution (sdist) for any architecture with Rust toolchain

Features

  • Read DMG trailer (koly) metadata and checksum fields.
  • Parse plist metadata and return a JSON-serializable structure.
  • Extract metadata candidates for:
    • creation and modification dates/timestamps
    • author/creator-like fields
    • creation application/tool fields
  • List partitions and their BLKX chunk tables.
  • Inspect GPT partition-table metadata when GPT is present in DMG partitions.
  • Inspect filesystem metadata for FAT12/16/32 partitions.
  • Auto-detect and inspect HFS+/APFS metadata using dpp.
  • Decompress and read partition payload bytes.
  • Verify data fork CRC32 checksum.
  • List and extract files from FAT32 DMG partitions.
  • List and extract files from auto-detected HFS+/APFS DMG filesystems.
  • Create new DMGs from a source directory.

Installation

From PyPI

pip install pydmg

From source (local development)

Requirements:

  • Python 3.9+
  • Rust toolchain (stable)
  • C/C++ compiler toolchain

Platform notes for source builds:

  • Linux: install build-essential, pkg-config, libbz2-dev, liblzma-dev
  • macOS: install Xcode Command Line Tools and pkg-config
  • Windows: install Visual Studio Build Tools (MSVC C++)
pip install -e ".[dev]"

Quick Start

from pathlib import Path
import pydmg

info = pydmg.inspect("example.dmg")
print(info["koly"]["version"])
print(info["checksum"]["data_fork_checksum_matches"])

parts = pydmg.list_partitions("example.dmg")
print([p["name"] for p in parts])

gpt_info = pydmg.inspect_gpt("example.dmg")
print(gpt_info["has_gpt"])

fat_entries = pydmg.list_fat32_entries("example.dmg", partition_index=1)
print(fat_entries[:5])

pydmg.extract_fat32("example.dmg", "./out", partition_index=1)

fs_info = pydmg.inspect_filesystems("example.dmg")
print(fs_info["fat_filesystems"])

# For HFS+/APFS DMGs:
# entries = pydmg.list_apple_entries("macos_installer.dmg", "/")
# pydmg.extract_apple_file("macos_installer.dmg", "/path/in/image.pkg", "./image.pkg")

pydmg.create_dmg(
    source_dir=Path("./payload"),
    output_path=Path("./payload.dmg"),
    volume_label="PAYLOAD",
    total_sectors=32768,
)

API Surface

Top-level functions

  • inspect(path)
  • inspect_filesystems(path)
  • list_partitions(path)
  • inspect_gpt(path, partition_index=None, strict=False)
  • read_partition(path, index)
  • extract_partition(path, index, output_path)
  • compute_data_checksum(path)
  • verify_data_checksum(path)
  • list_fat32_entries(path, partition_index=1)
  • extract_fat32(path, output_dir, partition_index=1, overwrite=False)
  • list_apple_entries(path, directory_path="/")
  • read_apple_file(path, file_path)
  • extract_apple_file(path, file_path, output_path)
  • create_dmg(source_dir, output_path, volume_label="PYDMG", total_sectors=32768)

Object API

DmgImage(path) provides convenience wrappers over the same operations.

Function Reference

All paths accept str or pathlib.Path.

Common error behavior:

  • Raises RuntimeError when parsing, decompression, or filesystem reads fail.
  • Raises ValueError for invalid user input in some APIs (for example invalid create_dmg arguments).

DMG inspection and metadata

inspect(path) -> dict

  • Returns DMG-level details including:
  • koly trailer values
  • checksum fields and CRC comparison result
  • parsed plist
  • metadata_candidates (date/author/tool-like fields)
  • partition metadata and chunk tables

inspect_filesystems(path) -> dict

  • Returns detected filesystem metadata including:
  • fat_filesystems list (FAT12/16/32 metadata)
  • apple_filesystem (HFS+/APFS metadata when detected)
  • errors list for non-fatal detection failures

inspect_gpt(path, partition_index=None, strict=False) -> dict

  • Scans one partition or all partitions for GPT metadata.
  • If no GPT is found and strict=False, returns has_gpt: false.
  • If no GPT is found and strict=True, raises RuntimeError.

list_partitions(path) -> list[dict]

  • Returns parsed DMG partition records with BLKX chunk info.

Example:

import pydmg

info = pydmg.inspect("image.dmg")
print(info["metadata_candidates"])

fs = pydmg.inspect_filesystems("image.dmg")
print(fs["fat_filesystems"])
print(fs["apple_filesystem"])

gpt = pydmg.inspect_gpt("image.dmg", strict=False)
print(gpt["has_gpt"])

parts = pydmg.list_partitions("image.dmg")
print(len(parts))

Partition payload and checksums

read_partition(path, index) -> bytes

  • Reads and decompresses the partition payload at index.

extract_partition(path, index, output_path) -> int

  • Writes that payload to disk and returns bytes written.

compute_data_checksum(path) -> int

  • Computes DMG data-fork CRC32.

verify_data_checksum(path) -> bool

  • Compares computed CRC32 to the trailer-declared checksum.

Example:

payload = pydmg.read_partition("image.dmg", 0)
print(len(payload))

written = pydmg.extract_partition("image.dmg", 0, "part0.bin")
print(written)

print(pydmg.compute_data_checksum("image.dmg"))
print(pydmg.verify_data_checksum("image.dmg"))

FAT32 filesystem helpers

list_fat32_entries(path, partition_index=1) -> list[dict]

  • Lists FAT entries with path/type/size metadata.

extract_fat32(path, output_dir, partition_index=1, overwrite=False) -> list[str]

  • Extracts files from the selected FAT partition.
  • Returns extracted relative paths.

Example:

entries = pydmg.list_fat32_entries("image.dmg", partition_index=1)
print(entries[:3])

files = pydmg.extract_fat32("image.dmg", "out/fat", partition_index=1, overwrite=True)
print(files[:3])

HFS+ and APFS filesystem helpers

list_apple_entries(path, directory_path="/") -> list[dict]

  • Auto-detects HFS+ or APFS and lists directory entries.

read_apple_file(path, file_path) -> bytes

  • Reads a single file from detected HFS+/APFS filesystem.

extract_apple_file(path, file_path, output_path) -> int

  • Writes file content to output_path and returns bytes written.

Example:

entries = pydmg.list_apple_entries("mac_image.dmg", "/")
print(entries[:5])

data = pydmg.read_apple_file("mac_image.dmg", "/README.txt")
print(len(data))

written = pydmg.extract_apple_file("mac_image.dmg", "/README.txt", "out/README.txt")
print(written)

DMG creation

create_dmg(source_dir, output_path, volume_label="PYDMG", total_sectors=32768) -> None

  • Creates a DMG from a directory.
  • total_sectors uses 512-byte sectors.

Example:

from pathlib import Path
import pydmg

pydmg.create_dmg(
    source_dir=Path("payload"),
    output_path=Path("payload.dmg"),
    volume_label="PAYLOAD",
    total_sectors=32768,
)

DmgImage convenience object

DmgImage(path) wraps the same top-level APIs as instance methods.

Example:

img = pydmg.DmgImage("image.dmg")
print(img.inspect()["koly"]["version"])
print(img.inspect_filesystems()["apple_filesystem"])
print(img.checksum_valid())

Testing

pytest

The test suite covers:

  • DMG creation from a fixture directory
  • inspection payload completeness
  • checksum computation/verification
  • GPT inspection behavior (non-GPT reporting and strict mode)
  • partition read/extract
  • FAT32 listing and extraction
  • filesystem metadata inspection (FAT + HFS+/APFS auto-detect behavior)
  • HFS+ positive listing/read/extract using upstream hfsplus-rs fixture image
  • APFS positive listing/read/extract using non-malware linearmouse fixture image
  • partition index error behavior

API Docs (pydoc)

Generate HTML API docs locally:

python scripts/build_pydoc.py

This writes pydmg.html in the current directory. CI also verifies that pydoc build succeeds.

GitHub Actions and PyPI

This repo includes workflows for:

  • CI: build + test on Linux, macOS, and Windows
  • Release: build wheels for major architectures, build source distribution, and publish to PyPI

Release workflow targets:

  • Linux: x86_64, aarch64
  • macOS: x86_64, arm64
  • Windows: x86_64
  • Plus sdist for architecture-independent source release

For publishing, configure PyPI trusted publishing for this repository and push a tag like v0.1.0.

Detailed release steps are documented in RELEASE.md.

Licensing Notes

  • Project license: MIT (LICENSE)
  • Third-party attribution and fixture provenance: THIRD_PARTY_NOTICES.md
  • Test fixture source details: tests/fixtures/README.md
  • No Paragon APFS SDK code is included

Notes on metadata completeness

DMG metadata fields vary by producer and format. pydmg returns:

  • parsed plist payload (JSON-compatible representation)
  • extracted metadata candidates based on key patterns

This gives broad coverage of creation dates, creators/authors, and creation applications when present.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pydmg-0.1.0.tar.gz (3.0 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

pydmg-0.1.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (885.3 kB view details)

Uploaded PyPymanylinux: glibc 2.17+ ARM64

pydmg-0.1.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (885.4 kB view details)

Uploaded PyPymanylinux: glibc 2.17+ ARM64

pydmg-0.1.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (885.8 kB view details)

Uploaded PyPymanylinux: glibc 2.17+ ARM64

pydmg-0.1.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (888.7 kB view details)

Uploaded PyPymanylinux: glibc 2.17+ ARM64

pydmg-0.1.0-cp39-abi3-win_amd64.whl (670.3 kB view details)

Uploaded CPython 3.9+Windows x86-64

pydmg-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (905.4 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ x86-64

pydmg-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (891.0 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ARM64

pydmg-0.1.0-cp39-abi3-macosx_11_0_arm64.whl (791.6 kB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

pydmg-0.1.0-cp39-abi3-macosx_10_12_x86_64.whl (802.3 kB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

Details for the file pydmg-0.1.0.tar.gz.

File metadata

  • Download URL: pydmg-0.1.0.tar.gz
  • Upload date:
  • Size: 3.0 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pydmg-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c29ff92877cc1bba84d7110d40dd834c0951964589493505bec38edb278a3c09
MD5 1b863841f055f4776501d7241af70459
BLAKE2b-256 bb749dee1f734480d33d1a906bf2d550c3039f1408ec489f7f560f5a1378c030

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydmg-0.1.0.tar.gz:

Publisher: release.yml on bwhitn/pydmg

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pydmg-0.1.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for pydmg-0.1.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 edd9927c6132705a4bc91cfe6101ed26a58039ac50d8a6a797400e949ae056b9
MD5 83f01d68063a5460eb8d98e2b3f49ea3
BLAKE2b-256 a3a1c1ba587fd75b91f2957df0224fc93dbf4308c298c9244f5f08515d7a4617

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydmg-0.1.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on bwhitn/pydmg

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pydmg-0.1.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for pydmg-0.1.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 a1295f99f0ff4a58556cd86f3237ed41ef2650697cc0c2dbf87181602965ff9c
MD5 addab5433d30a9db0b00690ba1a8b33d
BLAKE2b-256 3b1f0eca26485922621fb138c2e9ed9ef303e4802aed7f5660d628884bbaf4a2

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydmg-0.1.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on bwhitn/pydmg

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pydmg-0.1.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for pydmg-0.1.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 731b359350fd2eb0e87f229a13adcc42169879b53c96c826c77704858275a3c2
MD5 d224bab62577aab1eac3ef3ac0c968d5
BLAKE2b-256 9159f6bef7edb8b1ec8074cb2a02f301a350598ae29419e9bf53572bc9e877e0

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydmg-0.1.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on bwhitn/pydmg

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pydmg-0.1.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for pydmg-0.1.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 d91aa051b74a5ef8fd474fd1da3c621551c9bc62eb6723f3727cfb55adfdea49
MD5 a9ce1a784095076b3b3f8873da56746a
BLAKE2b-256 ecffa7c86216a8ca089bc82a428a118665a2e95a286de97dc1b5f233e5dcdfef

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydmg-0.1.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on bwhitn/pydmg

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pydmg-0.1.0-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: pydmg-0.1.0-cp39-abi3-win_amd64.whl
  • Upload date:
  • Size: 670.3 kB
  • Tags: CPython 3.9+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pydmg-0.1.0-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 949c0347d761d8618faaa576d53246a6db8706b39ec089e26d9be54247d19f6e
MD5 92dd54af95fd73e4f2629130adfa842a
BLAKE2b-256 1ebe83a81274df0cc4262e0aeb64b2dbb330e29e55c33324deb4643519ccb956

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydmg-0.1.0-cp39-abi3-win_amd64.whl:

Publisher: release.yml on bwhitn/pydmg

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pydmg-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pydmg-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 15a58ca34a73471b7310ba82a95237e50111412de57d228ac0fbece35cb957b3
MD5 36a292183d7045273c518e00009e7ebd
BLAKE2b-256 be546dca5b5981465b078b1a1c06c1bce047a9b00017fc36b24e8275d2315eb2

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydmg-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on bwhitn/pydmg

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pydmg-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for pydmg-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 63000e338edacedc4f78c9a88b62b507d2506823b50db6daae000e74d6677987
MD5 a33e6debd06ed57b4d2443cbb10806dd
BLAKE2b-256 a82cd42c2834771b8ba44cbd8b66a289dc8f9f15d37ea8d8efb558d3eeafffb6

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydmg-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on bwhitn/pydmg

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pydmg-0.1.0-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

  • Download URL: pydmg-0.1.0-cp39-abi3-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 791.6 kB
  • Tags: CPython 3.9+, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pydmg-0.1.0-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 bfde662f7effd90e648c93c20a13e3658ba80b951a86eb2ddf8e2a7bc546b240
MD5 250746bd8d2e676581031db51e775693
BLAKE2b-256 f76678cf97ce1c2be91f375f1d2b15f95e545cde7dad00a913d19e3391f6ecc4

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydmg-0.1.0-cp39-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on bwhitn/pydmg

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pydmg-0.1.0-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for pydmg-0.1.0-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 ff7d28c56d21acd6135e6254a271cd68f8966a315540ba9e6194b61a96b6af9f
MD5 defea62a14df0db5193d9e21f894b75a
BLAKE2b-256 c4dba317d6cf3be37ff0d5459780585ab7cbd5b1c7aaa3f5d9dccc0e37db78c4

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydmg-0.1.0-cp39-abi3-macosx_10_12_x86_64.whl:

Publisher: release.yml on bwhitn/pydmg

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page