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.1.

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.1.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.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (885.4 kB view details)

Uploaded PyPymanylinux: glibc 2.17+ ARM64

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

Uploaded PyPymanylinux: glibc 2.17+ ARM64

pydmg-0.1.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (885.6 kB view details)

Uploaded PyPymanylinux: glibc 2.17+ ARM64

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

Uploaded PyPymanylinux: glibc 2.17+ ARM64

pydmg-0.1.1-cp39-abi3-win_amd64.whl (670.2 kB view details)

Uploaded CPython 3.9+Windows x86-64

pydmg-0.1.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (905.3 kB view details)

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

pydmg-0.1.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (890.9 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ARM64

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

Uploaded CPython 3.9+macOS 11.0+ ARM64

pydmg-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl (801.5 kB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

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

File metadata

  • Download URL: pydmg-0.1.1.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.1.tar.gz
Algorithm Hash digest
SHA256 852ddc7c5a0b11071e8241b9b83eca1a48a741be0cec68956fbce74b2dd242e4
MD5 f3dd1ca0fd2abe480bbbb89f33b65328
BLAKE2b-256 06cbf4951db722b8c36332f6cd555d7e5c58542b121da872a150c0bd290b549e

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydmg-0.1.1.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.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for pydmg-0.1.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 d0763471594b1a42833627636aa4646e40292d9805a9b56fdb5004655d3303f9
MD5 e467bfb7037ac41ab1fce3ace8ea9f1f
BLAKE2b-256 08b94bb24f29460b6e4d111dd759b8cc71351cde107e912256a506a129ae4d75

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydmg-0.1.1-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.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for pydmg-0.1.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 6665cfda810fb49c57de3daf31956023398a83499f9478a8696ba09430bdeadb
MD5 279473dd3081979d1d3c81121123c7ba
BLAKE2b-256 1daee3ee2dfc89139ef0b6f0f666a0a9ea471312500ad307a0bab76efb3a17f1

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydmg-0.1.1-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.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for pydmg-0.1.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 47b61f6fd4d7de94fb021c76b443847dbeb9eac025f33ff3078b5683676df29b
MD5 71c90435dd92973cbb5e02b02f8bcfa5
BLAKE2b-256 5b8e5bc1e7b19702065eb9cbfb7190e703a6b58e67943b8d2eb45c9952cc96c2

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydmg-0.1.1-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.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for pydmg-0.1.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 229a39711b1c67f9be52ca441840c6ad57faa5651ea662ae47e3116cff89c57d
MD5 0320e6378dc3e7aefa9ea2e016b684d8
BLAKE2b-256 837a7b2244492d48efca68561f1e973f82d79876bfc13d13c63fe4821584cb0f

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydmg-0.1.1-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.1-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: pydmg-0.1.1-cp39-abi3-win_amd64.whl
  • Upload date:
  • Size: 670.2 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.1-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 43f619380eac66bc99cfe348269c6f03f8d7bfd5e69f0522e1267958d45f41e9
MD5 b7f584cf4204ff71c33ff2ce33a26102
BLAKE2b-256 3c2d4f861f7ade5fd31773116a6c7b5e32cf3abf95c6645789108ddaa89b6a86

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydmg-0.1.1-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.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pydmg-0.1.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 a1054f008b96b44092e7840a8ae2457004c58ebd488aefcb7041a756e0d8100b
MD5 f66863bb47530e35a582fb4e27b93200
BLAKE2b-256 3bc0b58320ca24e9445bf414183ab63731be0007898c74c1bdfe80387d14097a

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydmg-0.1.1-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.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for pydmg-0.1.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 0e2adf8aa8e599d2e58d13f9024d13633e4c85f38dab97ff5b900719980d3267
MD5 c24978db32095c2ef2d7eba66f558927
BLAKE2b-256 bd8288974c2ccef35f89233043350a6cc98b777f1d1d2fcf0a058ed5b30653b5

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydmg-0.1.1-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.1-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

  • Download URL: pydmg-0.1.1-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.1-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 fa000d0002c90309e9ebf211fd3a09da5902a99fffce8281b2bfa3806b450faa
MD5 54b82594f982e083b816f49ce7eab4ca
BLAKE2b-256 29426dad077349d07b857e2acd615c655854d3ea244fc1172782d004647a6356

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydmg-0.1.1-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.1-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for pydmg-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 39288209874d1e84e80a47e163118aff4b278c58c618171c3d5604ec5f1d2101
MD5 262e3626135af1a56127e541ed42fe29
BLAKE2b-256 52f3016f126d4e56cbfea5c5ee7962a3037af5250154deca43763f37229c8b53

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydmg-0.1.1-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