or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli-commands.mdindex.mdpackage-conversion.mdtag-management.mdwheelfile-ops.md

wheelfile-ops.mddocs/

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

```