Wheel Files

Read and write wheel files. The reader checks each file against the RECORD file as it is read. The writer computes RECORD as files are added and generates the WHEEL file from the wheel’s name.

Added in version 26.4.

Usage

Write a wheel by name. The name, version, build tag and tags come from the filename, and WHEEL and RECORD are generated when the context exits:

from packaging.wheelfile import WheelWriter

with WheelWriter("example-1.0-py3-none-any.whl", generator="mytool 1.0") as writer:
    writer.write_file("example/__init__.py", b"print('hello')\n")
    writer.write_data_file("scripts/example", b"#!python\n", mode=0o755)
    writer.write_dist_info_file("METADATA", metadata_bytes)

A file object can be used instead of a path. The wheel name must then be given as WheelMetadata, since there is no filename to parse. The same applies to reading:

>>> from io import BytesIO
>>> from packaging.wheelfile import WheelMetadata, WheelReader, WheelWriter
>>> buffer = BytesIO()
>>> metadata = WheelMetadata.from_filename("example-1.0-py3-none-any.whl")
>>> with WheelWriter(buffer, generator="mytool 1.0", metadata=metadata) as writer:
...     writer.write_file("example/__init__.py", b"print('hello')\n")
...     writer.write_dist_info_file("METADATA", b"Metadata-Version: 2.4\nName: example\nVersion: 1.0\n")
>>> with WheelReader(buffer) as reader:
...     (reader.name, str(reader.version))
...     reader.dist_info_dir
...     reader.validate_record()
...     reader.read_file("example/__init__.py")
...     print(reader.read_dist_info_file("WHEEL").decode())
('example', '1.0')
'example-1.0.dist-info'
b"print('hello')\n"
Wheel-Version: 1.0
Generator: mytool 1.0
Root-Is-Purelib: true
Tag: py3-none-any

Reading a file that does not match RECORD raises WheelError:

>>> from zipfile import ZipFile
>>> with ZipFile(buffer, "a") as zf:
...     zf.writestr("extra.txt", "not in RECORD")
>>> with WheelReader(buffer) as reader:
...     reader.read_file("extra.txt")
Traceback (most recent call last):
    ...
packaging.wheelfile.WheelError: No hash found for file 'extra.txt'

Reproducible wheels

Every archive member has a timestamp and permission bits. By default, members written from bytes or file objects get mode 0o664 and the timestamp 1980-01-01, the earliest the ZIP format can store. Members written from a path keep the permissions of the file on disk. The timestamp and mode arguments of WheelWriter change the defaults for every member, including the generated WHEEL and RECORD files, and the same arguments on each write method override them for one member.

If the SOURCE_DATE_EPOCH environment variable is set when a WheelWriter is created and no timestamp is given, its value is used as the default timestamp. Timestamps outside the range the ZIP format can store are clamped to that range.

Reference

class packaging.wheelfile.WheelWriter
__init__(path_or_fd, /, *, generator, metadata=None, root_is_purelib=True, compress=True, hash_algorithm='sha256', timestamp=None, mode=0o664)

Write a wheel file, generating WHEEL and RECORD.

This is a context manager; the archive is created on entry. On a clean exit, WHEEL is written unless it was written explicitly, and RECORD is written last. If the body raises, a wheel given by path is removed.

Parameters:
  • path_or_fd (str | PathLike[str] | IO[bytes]) – path of the wheel to create, or a binary file object

  • generator (str) – the name and version of the tool creating the wheel

  • metadata (WheelMetadata | None) – the wheel name, version, build tag and tags; if omitted, they are parsed from the filename

  • root_is_purelib (bool) – whether the root of the archive is purelib

  • compress (bool) – whether to deflate the archive members

  • hash_algorithm (str) – the hashlib algorithm used in RECORD

  • timestamp (datetime | None) – the default timestamp for every archive member, including the generated WHEEL and RECORD files; if omitted, the value of the SOURCE_DATE_EPOCH environment variable, or else 1980-01-01

  • mode (int) – the default permission bits for members written from bytes or file objects, including WHEEL and RECORD

Raises:
  • WheelError – if a file object is given without metadata, or SOURCE_DATE_EPOCH is not an integer

  • ValueError – if the hash algorithm is unavailable or weak

Return type:

None

write_file(name, contents, *, timestamp=None, mode=None)

Write a file to the archive and record its hash.

Parameters:
  • name (str | PurePath) – the path of the file inside the archive

  • contents (bytes | PathLike[str] | IO[bytes]) – the file contents, a path to a file to copy, or a binary file object; a str is rejected, as it is too easy to mistake for a path

  • timestamp (datetime | None) – the timestamp of the member; the writer default if omitted

  • mode (int | None) – the permission bits of the member; if omitted, a path or file object keeps its own permissions and anything else gets the writer default

Return type:

None

write_files_from_directory(directory)

Write every file under a directory, in sorted order, keeping relative paths.

An existing RECORD file is skipped, so an unpacked wheel can be packed again. An existing WHEEL file is kept as is.

Raises:

WheelError – if the directory does not exist

Parameters:

directory (str | PathLike[str])

Return type:

None

write_data_file(filename, contents, *, timestamp=None, mode=None)

Write a file relative to the .data directory.

Parameters:
  • filename (str) – path inside the .data directory, starting with one of purelib, platlib, headers, scripts or data

  • contents (bytes | PathLike[str] | IO[bytes])

  • timestamp (datetime | None)

  • mode (int | None)

Raises:

WheelError – if the first path component is not one of those

Return type:

None

write_dist_info_file(filename, contents, *, timestamp=None, mode=None)

Write a file relative to the .dist-info directory.

Parameters:
Return type:

None

packaging.wheelfile.write_wheelfile(fp, /, *, generator, tags, build_tag=(), root_is_purelib)

Write the contents of a WHEEL file to a binary stream.

Parameters:
  • generator (str) – the name and version of the tool creating the wheel

  • tags (Iterable[Tag]) – the compatibility tags of the wheel

  • build_tag (BuildTag) – the build tag of the wheel, if any

  • root_is_purelib (bool) – whether the root of the archive is purelib

  • fp (IO[bytes])

Return type:

None

class packaging.wheelfile.WheelReader

Read a wheel file, verifying its contents against RECORD.

This is a context manager; the archive is opened on entry and closed on exit.

Parameters:

path_or_fd – path to the wheel, or a binary file object; with a path, the name and version are taken from the filename

Raises:

WheelError – if the filename is not a valid wheel filename

__init__(path_or_fd)
Parameters:

path_or_fd (str | PathLike[str] | IO[bytes])

Return type:

None

property dist_info_dir: str

The name of the .dist-info directory.

property data_dir: str

The name of the .data directory.

property dist_info_filenames: list[PurePath]

The paths of all files in the .dist-info directory.

property filenames: list[PurePath]

The paths of all files in the archive.

iterate_contents()

Iterate over the files listed in RECORD.

The stream of each element is checked against RECORD as it is read, and closed when the iteration advances to the next element.

Return type:

Iterator[WheelContentElement]

validate_record()

Read every file in the archive and check it against RECORD.

Raises:

WheelError – if a file is missing from RECORD, or its size or hash does not match

Return type:

None

extractall(base_path)

Extract all files into an existing directory, verifying them against RECORD.

Raises:

WheelError – if the directory does not exist, a file fails validation, or a member path escapes the directory

Parameters:

base_path (str | PathLike[str])

Return type:

None

open(archive_name)

Open a file in the archive for reading.

Parameters:

archive_name (str) – the full path of the file inside the archive

Raises:

WheelError – if the file is not listed in RECORD

Return type:

WheelArchiveFile

read_file(archive_name)

Read a file in the archive, verifying it against RECORD.

Parameters:

archive_name (str)

Return type:

bytes

read_data_file(filename)

Read a file relative to the .data directory.

Parameters:

filename (str)

Return type:

bytes

read_dist_info_file(filename)

Read a file relative to the .dist-info directory.

Parameters:

filename (str)

Return type:

bytes

class packaging.wheelfile.WheelArchiveFile

A read-only binary stream for one member of a wheel.

The contents are checked against the RECORD file as they are read. A size or hash mismatch raises WheelError once the stream has been read in full.

__init__(fp, arcname, record_entry)
Parameters:
Return type:

None

class packaging.wheelfile.WheelMetadata

The parts of a wheel filename that identify the wheel.

name: NormalizedName

Alias for field number 0

version: Version

Alias for field number 1

build_tag: BuildTag

Alias for field number 2

tags: frozenset[Tag]

Alias for field number 3

classmethod from_filename(fname)

Parse a wheel filename.

Raises:

packaging.utils.InvalidWheelFilename – if the filename is invalid

Parameters:

fname (str)

Return type:

WheelMetadata

static __new__(_cls, name, version, build_tag, tags)

Create new instance of WheelMetadata(name, version, build_tag, tags)

Parameters:
class packaging.wheelfile.WheelRecordEntry

One row of the RECORD file.

hash_algorithm: str

Alias for field number 0

hash_value: bytes

Alias for field number 1

filesize: int

Alias for field number 2

static __new__(_cls, hash_algorithm, hash_value, filesize)

Create new instance of WheelRecordEntry(hash_algorithm, hash_value, filesize)

Parameters:
  • hash_algorithm (str)

  • hash_value (bytes)

  • filesize (int)

class packaging.wheelfile.WheelContentElement

A file yielded by WheelReader.iterate_contents().

path: PurePath

Alias for field number 0

hash_value: bytes

Alias for field number 1

size: int

Alias for field number 2

stream: WheelArchiveFile

Alias for field number 3

static __new__(_cls, path, hash_value, size, stream)

Create new instance of WheelContentElement(path, hash_value, size, stream)

Parameters:
class packaging.wheelfile.WheelError

Raised when a wheel is malformed or fails validation.

__init__(*args, **kwargs)
classmethod __new__(*args, **kwargs)