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

tag-management.mddocs/

0

# Wheel Tag Management

1

2

Modify wheel filename tags for Python version, ABI, and platform compatibility without rebuilding the package. Enables retargeting wheels for different Python versions or platforms when the code is compatible.

3

4

## Capabilities

5

6

### Tag Modification Function

7

8

Main function for modifying wheel tags and creating new wheel files with updated compatibility information.

9

10

```python { .api }

11

def tags(

12

wheel: str,

13

python_tags: str | None = None,

14

abi_tags: str | None = None,

15

platform_tags: str | None = None,

16

build_tag: str | None = None,

17

remove: bool = False,

18

) -> str:

19

"""

20

Modify wheel tags and create new wheel file.

21

22

Parameters:

23

- wheel: Path to input wheel file

24

- python_tags: Python version tags (e.g., "py38.py39")

25

- abi_tags: ABI tags (e.g., "cp38.cp39")

26

- platform_tags: Platform tags (e.g., "linux_x86_64.win_amd64")

27

- build_tag: Build tag (must start with digit, no dashes)

28

- remove: Delete original wheel file after creating new one

29

30

Returns:

31

Filename of newly created wheel

32

33

Tag modification syntax:

34

- Replace: "py38.py39" replaces all Python tags

35

- Append: "+py310" adds py310 to existing tags

36

- Remove: "-py37" removes py37 from existing tags

37

- Multiple: Dot-separated values for multiple tags

38

39

Raises:

40

- AssertionError: If internal WHEEL tags don't match filename

41

- WheelError: For invalid wheel files or format errors

42

"""

43

```

44

45

### Tag Computation Utilities

46

47

Helper functions for computing and manipulating tag sets.

48

49

```python { .api }

50

def _compute_tags(original_tags: Iterable[str], new_tags: str | None) -> set[str]:

51

"""

52

Compute final tag set based on modification rules.

53

54

Parameters:

55

- original_tags: Current tags from wheel

56

- new_tags: Tag modification string (None for no change)

57

58

Returns:

59

Final set of tags after applying modifications

60

61

Modification rules:

62

- None or empty: No change (returns original_tags)

63

- Starting with '+': Append tags (union operation)

64

- Starting with '-': Remove tags (difference operation)

65

- Other: Replace tags completely

66

- Dot-separated: Multiple tags in single string

67

"""

68

```

69

70

### Tag Validation

71

72

The tags function performs comprehensive validation to ensure wheel integrity:

73

74

1. **Filename Parsing**: Validates wheel filename format using WHEEL_INFO_RE

75

2. **Internal Consistency**: Verifies WHEEL file tags match filename tags

76

3. **Build Tag Consistency**: Ensures build tags match between filename and WHEEL file

77

4. **Tag Format**: Validates tag syntax and relationships

78

79

### Usage Examples

80

81

#### Basic Tag Modifications

82

83

```python

84

from wheel._commands.tags import tags

85

86

# Replace Python version tags

87

new_wheel = tags(

88

'package-1.0-py3-none-any.whl',

89

python_tags='py38.py39.py310'

90

)

91

# Result: package-1.0-py38.py39.py310-none-any.whl

92

93

# Add platform support

94

new_wheel = tags(

95

'package-1.0-py3-none-any.whl',

96

platform_tags='linux_x86_64.macosx_10_9_x86_64'

97

)

98

# Result: package-1.0-py3-none-linux_x86_64.macosx_10_9_x86_64.whl

99

100

# Set ABI tags for compiled extensions

101

new_wheel = tags(

102

'package-1.0-py38-abi3-linux_x86_64.whl',

103

abi_tags='cp38.cp39.cp310'

104

)

105

# Result: package-1.0-py38-cp38.cp39.cp310-linux_x86_64.whl

106

```

107

108

#### Append and Remove Operations

109

110

```python

111

# Append Python version

112

new_wheel = tags(

113

'package-1.0-py38.py39-none-any.whl',

114

python_tags='+py310'

115

)

116

# Result: package-1.0-py38.py39.py310-none-any.whl

117

118

# Remove specific version

119

new_wheel = tags(

120

'package-1.0-py37.py38.py39-none-any.whl',

121

python_tags='-py37'

122

)

123

# Result: package-1.0-py38.py39-none-any.whl

124

125

# Multiple operations (applied left to right)

126

new_wheel = tags(

127

'package-1.0-py37.py38-none-any.whl',

128

python_tags='-py37.+py39.+py310'

129

)

130

# Result: package-1.0-py38.py39.py310-none-any.whl

131

```

132

133

#### Build Tags

134

135

```python

136

# Add build tag

137

new_wheel = tags(

138

'package-1.0-py3-none-any.whl',

139

build_tag='20231201'

140

)

141

# Result: package-1.0-20231201-py3-none-any.whl

142

143

# Remove build tag

144

new_wheel = tags(

145

'package-1.0-20231201-py3-none-any.whl',

146

build_tag=''

147

)

148

# Result: package-1.0-py3-none-any.whl

149

```

150

151

#### File Management

152

153

```python

154

# Keep original file (default)

155

new_wheel = tags('package-1.0-py3-none-any.whl', python_tags='py39')

156

# Creates: package-1.0-py39-none-any.whl

157

# Keeps: package-1.0-py3-none-any.whl

158

159

# Remove original file

160

new_wheel = tags(

161

'package-1.0-py3-none-any.whl',

162

python_tags='py39',

163

remove=True

164

)

165

# Creates: package-1.0-py39-none-any.whl

166

# Deletes: package-1.0-py3-none-any.whl

167

```

168

169

#### Complex Tag Combinations

170

171

```python

172

# Multiple tag types simultaneously

173

new_wheel = tags(

174

'package-1.0-py3-none-any.whl',

175

python_tags='py38.py39.py310',

176

abi_tags='cp38.cp39.cp310',

177

platform_tags='linux_x86_64.win_amd64',

178

build_tag='20231201'

179

)

180

# Result: package-1.0-20231201-py38.py39.py310-cp38.cp39.cp310-linux_x86_64.win_amd64.whl

181

```

182

183

#### Programmatic Tag Management

184

185

```python

186

from wheel._commands.tags import tags, _compute_tags

187

from wheel.wheelfile import WheelFile

188

189

# Analyze current tags

190

with WheelFile('package-1.0-py3-none-any.whl', 'r') as wf:

191

parsed = wf.parsed_filename

192

current_python = parsed.group('pyver').split('.')

193

current_abi = parsed.group('abi').split('.')

194

current_platform = parsed.group('plat').split('.')

195

196

print(f"Current Python tags: {current_python}")

197

print(f"Current ABI tags: {current_abi}")

198

print(f"Current platform tags: {current_platform}")

199

200

# Compute new tag set

201

new_python_tags = _compute_tags(current_python, '+py311')

202

print(f"New Python tags: {sorted(new_python_tags)}")

203

204

# Apply changes

205

new_wheel = tags(

206

'package-1.0-py3-none-any.whl',

207

python_tags='.'.join(sorted(new_python_tags))

208

)

209

```

210

211

### Error Handling

212

213

```python

214

from wheel._commands.tags import tags

215

from wheel.wheelfile import WheelError

216

217

try:

218

# This will raise AssertionError if tags are inconsistent

219

new_wheel = tags('corrupted-wheel.whl', python_tags='py39')

220

except AssertionError as e:

221

print(f"Wheel integrity error: {e}")

222

except WheelError as e:

223

print(f"Wheel format error: {e}")

224

```

225

226

### Common Use Cases

227

228

#### Cross-Platform Distribution

229

230

```python

231

# Create platform-specific variants from universal wheel

232

platforms = ['linux_x86_64', 'macosx_10_9_x86_64', 'win_amd64']

233

234

for platform in platforms:

235

platform_wheel = tags(

236

'package-1.0-py3-none-any.whl',

237

platform_tags=platform

238

)

239

print(f"Created: {platform_wheel}")

240

```

241

242

#### Python Version Compatibility

243

244

```python

245

# Update wheel for newer Python versions

246

python_versions = ['py39', 'py310', 'py311']

247

248

updated_wheel = tags(

249

'package-1.0-py38-none-any.whl',

250

python_tags='.'.join(python_versions)

251

)

252

print(f"Updated wheel: {updated_wheel}")

253

```

254

255

#### ABI Tag Updates

256

257

```python

258

# Convert from specific ABI to abi3 (stable ABI)

259

stable_wheel = tags(

260

'package-1.0-py38-cp38-linux_x86_64.whl',

261

abi_tags='abi3'

262

)

263

print(f"Stable ABI wheel: {stable_wheel}")

264

```

265

266

## Types

267

268

```python { .api }

269

from collections.abc import Iterable

270

from typing import Literal

271

272

# No additional types beyond function signatures

273

# Uses standard library types and wheel.wheelfile.WheelFile

274

```