0
# WheelFile Operations
1
2
Core functionality for reading, writing, and manipulating wheel archives. The WheelFile class extends Python's ZipFile with wheel-specific features including hash verification, reproducible builds, and wheel format compliance.
3
4
## Capabilities
5
6
### WheelFile Class
7
8
A ZipFile derivative that reads SHA-256 hashes from .dist-info/RECORD and verifies file integrity during read operations.
9
10
```python { .api }
11
class WheelFile(ZipFile):
12
"""
13
A ZipFile derivative class that also reads SHA-256 hashes from
14
.dist-info/RECORD and checks any read files against those.
15
"""
16
17
def __init__(
18
self,
19
file: str | os.PathLike[str],
20
mode: Literal["r", "w", "x", "a"] = "r",
21
compression: int = ZIP_DEFLATED,
22
):
23
"""
24
Initialize wheel file.
25
26
Parameters:
27
- file: Path to wheel file
28
- mode: File mode ('r', 'w', 'x', 'a')
29
- compression: Compression method (ZIP_DEFLATED default)
30
31
Raises:
32
- WheelError: If filename doesn't match wheel naming convention
33
"""
34
35
parsed_filename: re.Match[str]
36
"""Regex match object containing parsed wheel filename components."""
37
38
dist_info_path: str
39
"""Path to .dist-info directory within wheel."""
40
41
record_path: str
42
"""Path to RECORD file within wheel."""
43
```
44
45
### File Operations
46
47
Read and write files within wheel archives with automatic hash verification and generation.
48
49
```python { .api }
50
def open(
51
self,
52
name_or_info: str | ZipInfo,
53
mode: Literal["r", "w"] = "r",
54
pwd: bytes | None = None,
55
) -> IO[bytes]:
56
"""
57
Open file in wheel with hash verification.
58
59
Parameters:
60
- name_or_info: Filename or ZipInfo object
61
- mode: File mode ('r' or 'w')
62
- pwd: Password for encrypted files
63
64
Returns:
65
File-like object
66
67
Raises:
68
- WheelError: If file hash doesn't match RECORD or file not in RECORD
69
"""
70
71
def write(
72
self,
73
filename: str,
74
arcname: str | None = None,
75
compress_type: int | None = None,
76
) -> None:
77
"""
78
Write file to wheel archive.
79
80
Parameters:
81
- filename: Path to source file
82
- arcname: Archive name (uses filename if None)
83
- compress_type: Compression method override
84
"""
85
86
def writestr(
87
self,
88
zinfo_or_arcname: str | ZipInfo,
89
data: bytes | str,
90
compress_type: int | None = None,
91
) -> None:
92
"""
93
Write string or bytes data to wheel archive.
94
95
Parameters:
96
- zinfo_or_arcname: Archive filename or ZipInfo object
97
- data: Data to write (str will be UTF-8 encoded)
98
- compress_type: Compression method override
99
"""
100
101
def write_files(self, base_dir: str) -> None:
102
"""
103
Write entire directory tree to wheel.
104
105
Parameters:
106
- base_dir: Base directory to add to wheel
107
108
Note: Defers .dist-info files to write last, skips RECORD file
109
"""
110
111
def close(self) -> None:
112
"""
113
Close wheel file, automatically generating RECORD file for write mode.
114
"""
115
```
116
117
### Hash Utilities
118
119
URL-safe base64 encoding/decoding functions used for hash storage in RECORD files.
120
121
```python { .api }
122
def urlsafe_b64encode(data: bytes) -> bytes:
123
"""
124
URL-safe base64 encoding without padding.
125
126
Parameters:
127
- data: Bytes to encode
128
129
Returns:
130
Encoded bytes without '=' padding
131
"""
132
133
def urlsafe_b64decode(data: bytes) -> bytes:
134
"""
135
URL-safe base64 decoding without padding.
136
137
Parameters:
138
- data: Encoded bytes (padding added automatically)
139
140
Returns:
141
Decoded bytes
142
"""
143
```
144
145
### Reproducible Builds
146
147
Support for reproducible wheel builds using SOURCE_DATE_EPOCH environment variable.
148
149
```python { .api }
150
def get_zipinfo_datetime(
151
timestamp: float | None = None,
152
) -> tuple[int, int, int, int, int]:
153
"""
154
Get datetime tuple for ZipInfo, supporting reproducible builds.
155
156
Parameters:
157
- timestamp: Unix timestamp (uses SOURCE_DATE_EPOCH env var or current time)
158
159
Returns:
160
Datetime tuple (year, month, day, hour, minute) for ZipInfo
161
162
Note: Minimum timestamp is 1980-01-01 00:00:00 UTC (315532800)
163
"""
164
```
165
166
### Usage Examples
167
168
#### Reading Wheel Contents
169
170
```python
171
from wheel.wheelfile import WheelFile
172
173
with WheelFile('package-1.0-py3-none-any.whl', 'r') as wf:
174
# Access parsed filename components
175
name = wf.parsed_filename.group('name')
176
version = wf.parsed_filename.group('ver')
177
178
# List all files
179
for info in wf.filelist:
180
print(f"{info.filename} ({info.file_size} bytes)")
181
182
# Read specific file with hash verification
183
with wf.open('package/__init__.py') as f:
184
content = f.read().decode('utf-8')
185
print(content)
186
```
187
188
#### Creating New Wheel
189
190
```python
191
from wheel.wheelfile import WheelFile
192
import os
193
194
with WheelFile('new_package-1.0-py3-none-any.whl', 'w') as wf:
195
# Write files from directory (automatically generates hashes)
196
wf.write_files('build/lib/')
197
198
# Write individual files
199
wf.write('README.txt', 'new_package-1.0.dist-info/README.txt')
200
201
# Write string data
202
metadata = """Name: new-package
203
Version: 1.0
204
"""
205
wf.writestr('new_package-1.0.dist-info/METADATA', metadata)
206
207
# RECORD file is automatically generated on close()
208
```
209
210
#### Reproducible Builds
211
212
```python
213
import os
214
from wheel.wheelfile import WheelFile
215
216
# Set reproducible timestamp
217
os.environ['SOURCE_DATE_EPOCH'] = '1640995200' # 2022-01-01
218
219
with WheelFile('reproducible-1.0-py3-none-any.whl', 'w') as wf:
220
wf.write_files('src/')
221
# All files will have the same timestamp for reproducible builds
222
```
223
224
## Types
225
226
```python { .api }
227
from typing import IO, Literal
228
from zipfile import ZipInfo
229
import re
230
231
class WheelError(Exception):
232
"""Exception raised for wheel-related errors."""
233
pass
234
235
WHEEL_INFO_RE: re.Pattern[str]
236
"""
237
Regex pattern for parsing wheel filenames.
238
Matches: name-version(-build)?-python-abi-platform.whl
239
Groups: namever, name, ver, build, pyver, abi, plat
240
"""
241
242
MINIMUM_TIMESTAMP: int
243
"""Minimum timestamp for wheel files (315532800 = 1980-01-01 00:00:00 UTC)"""
244
```